Golang:当通过缓冲通道进行通信时,如何判断生产者或消费者是否较慢?



我在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问题了,在TOCTOU问题中,检查是针对单个时间点的,检查后状态可能立即发生变化,从而导致检查不正确/具有误导性。

任何去过赌场的人都知道,重要的不是你赢或输的次数,而是你赢或输的总金额。我可以输掉10手牌,每手10美元(总共损失100美元),然后赢得一只单手牌,获得150美元,我仍然会领先。

同样,生产者或消费者被阻塞的次数也不是有意义的。它是生产者或消费者被阻塞的总时间,这是决定它是否是最慢的组件的因素。

但是我想不出如何确定在读取/写入缓冲通道时阻塞的总量。或者我的google-fu不够好。有人有什么好主意吗?

我想到了几个解决方案。

<标题>1。秒表h1> 不具侵入性和最明显的是只注意时间,之前和之后,每个读或写。记录,求和,报告总I/O延迟。类似地,报告经过的处理时间。 <标题>2。基准h1> 一个合成工作台,每个阶段都要运行100万次相同的输入,产生一百万个相同的输出。

或者做一个"系统测试";你在哪里窃听生产过程中传递的信息,将它们写入日志文件;并将相关的日志信息重播给每个日志在你的各种管道阶段中,测量经过的时间。由于重放,将没有I/O节流。

<标题>

3。pub/sub h1> 新架构以使用更高的开销通信基础设施,如Kafka/0mq/RabbitMQ。修改参与节点数量在第一阶段处理,第二阶段等。现在的想法是压倒舞台在研究中,没有空闲周期,可以测量它的事务/秒吞吐量当饱和。或者,只分配每个阶段到它自己的节点,并测量{user, sys, idle}时间,

最新更新