Golang:当通过缓冲通道通信时,如何判断生产者还是消费者更慢?

jdg4fx2g  于 2022-12-25  发布在  Go
关注(0)|答案(1)|浏览(104)

我在Golang有一个应用程序,其中有一个管道设置,每个组件执行一些工作,然后通过缓冲通道沿着其结果传递给另一个组件,然后该组件在其输入上执行一些工作,然后通过另一个缓冲通道将其结果传递给另一个组件,依此类推。
C1 -C2 -C3 -...
其中C1、C2、C3是流水线中的组件,每个“-〉”是缓冲通道。
在Golang,缓冲通道非常好,因为它迫使快速生产者放慢速度,以匹配其下游消费者(或快速消费者放慢速度,以匹配其上游生产者)。因此,就像装配线一样,我的流水线与流水线中最慢的组件一样快。
问题是我想找出我的管道中哪个组件是最慢的,这样我就可以专注于改进该组件,以便使整个管道更快。
Golang迫使快速生产者或快速消费者减速的方法是,当生产者试图发送到已满的缓冲通道时,或者当消费者试图从空通道消费时,阻塞生产者。

outputChan <- result  // producer would block here when sending to full channel

input := <- inputChan // consumer would block here when consuming from empty channel

这使得我们很难分辨生产者和消费者中哪一个阻塞最多,也就是管道中最慢的组件。因为我不知道它阻塞了多长时间。阻塞时间最长的组件是最快的组件,阻塞时间最少(或者根本没有阻塞)的组件是最慢的组件。
我可以在读取或写入通道之前添加如下代码,以判断它是否会阻塞:

// for producer
if len(outputChan) == cap(outputChan) {
    producerBlockingCount++
}
outputChan <- result

// for consumer
if len(inputChan) == 0 {
    consumerBlockingCount++
}
input := <-inputChan

然而,这只会告诉我它会阻塞的次数,而不是它被阻塞的总时间。更不用说TOCTOU问题了,其中检查是针对单个时间点的,在检查之后状态可能会立即更改,从而使检查不正确/具有误导性。
任何曾经去过赌场的人都知道,重要的不是你赢或输的次数,重要的是你赢或输的钱的总数。我可以输10手,每手10美元(总共输100美元),然后赢150美元的一手,我仍然会领先。
同样,生产者或消费者被阻塞的次数并不是有意义的,生产者或消费者被阻塞的总时间才是决定它是否是最慢组件的因素。
但是我想不出任何方法来确定从缓冲通道阅读/写入时被阻塞的总量。或者我的google-fu不够好。有人有什么好主意吗?

46scxncf

46scxncf1#

有几个解决方案浮现在脑海中。

1.秒表

最简单、最明显的方法是记录每次读写之前和之后的时间,记录下来,求和,报告总的I/O延迟,同样地报告经过的处理时间。

2.基准

做一个合成工作台,让每一级在一百万个相同的输入上工作,产生一百万个相同的输出。
或者执行一个“系统测试”,监听流经生产的消息,将它们写入日志文件,并将相关日志消息重放到各个管道阶段,测量所用时间。由于进行了重放,因此不会有I/O限制。

3.发布/订阅

重新架构以使用开销更高的通信基础架构,如Kafka /0 mq/ RabbitMQ。更改参与阶段1处理、阶段2等的节点数量。其想法是压倒当前正在研究的阶段,没有空闲周期,以测量其饱和时的每秒事务吞吐量。
或者,在正常系统行为期间,仅将每个阶段分布到其自己的节点,并测量{user,sys,idle}时间。

相关问题