什么是缓冲通道的理想大小和工人数量?

时间:2018-05-09 20:44:24

标签: asynchronous go dispatcher goroutine

我正在尝试构建异步编解码器。我已经实现了一个可以访问缓冲的作业通道的作业调度程序

var JobChannel chan Job = make(chan Job, 100000)

调度员将工作人员的数量作为输入并将工作分配给他们

func StartDispacher(numberOfWorkers int){
    // start workers
    wg := &sync.WaitGroup{}
    wg.Add(numberOfWorkers)
    for i := int(1); i <= numberOfWorkers; i++ {
        go func(i int) {
            defer wg.Done()
            for j := range JobChannel {
                doWork(i, j)
            }
        }(i)
    }
}

我的主要功能启动调度员并继续为其提供工作(在这种情况下为200000个工作)

workDispatcher.StartDispacher(2*runtime.NumCPU())
for i := 0; i < 200000; i++ {
    j := workDispatcher.Job{
        BytePacket: d,
        JobType:    workDispatcher.DECODE_JOB,
    }
    workDispatcher.JobChannel <- j
}

经过实验:结果表明有两个因素会影响此代码的性能

  • 缓冲频道JobChannel
  • 的大小
  • func StartDispacher(numberOfWorkers int)
  • 的工人数量

是否有标准方法可以找到这些参数的最佳值,是否可以使这些值与运行代码的机器的物理设置无关?

3 个答案:

答案 0 :(得分:1)

您始终需要进行测量以确定系统在负载下的性能。这里的好消息是你只有两个变量,它们大多是独立的,所以它很容易推理。

工作者数确定您的并发性,因此对处理进行基准测试以查看最佳并发性。通常会有许多并发进程,其上的回报会急剧下降。

频道的大小就像任何其他&#34;缓冲区&#34;在一个系统中。较大的缓冲区可以处理较大的输入峰值,但代价是可能会导致较大的延迟和内存使用。

答案 1 :(得分:0)

答案是否定的。最佳设置不仅取决于您在doWork中运行的软件(该功能将依赖多少CPU密集和IO),还取决于您的硬件可以执行多少指令以及您的系统可以处理多少IO 。

这意味着,如果您的系统执行涉及互联网访问的活动,您的CPU有多少物理内核等等,它可能取决于您的系统安装了什么或没有安装SSD,甚至是您的带宽......

答案 2 :(得分:0)

实际上,我发现有三个缓冲区大小很重要:0,1和“发送总数的上限”。

0表示同步行为。

1给出异步行为:它在select语句中有用default

发送总数的上限提供了保证非阻塞行为:您可以在没有select的情况下发送给它,而不会冒着goroutine泄漏的风险。

其他数字可能会提供略微更好的吞吐量,但在规模上它们仍然会在包含通道内部互斥锁的缓存行上竞争,并且它们更有可能掩盖潜在的死锁和goroutine泄漏。