Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 如何有效使用频道_Performance_Go_Optimization_Benchmarking_Channels - Fatal编程技术网

Performance 如何有效使用频道

Performance 如何有效使用频道,performance,go,optimization,benchmarking,channels,Performance,Go,Optimization,Benchmarking,Channels,我在上面读到,一个应该使用最多1个通道长度 虽然我很清楚,使用100或1000的通道大小是非常糟糕的做法,但是我想知道为什么10的通道大小不是一个有效的选择。为了得出正确的结论,我遗漏了一些部分 在下面,您可以使用我的参数和一些基准测试支持的反参数 我理解,如果负责从该通道写入或读取的两个go例程在顺序写入或从该通道读取的过程中被其他IO操作中断,则无法从更高的通道缓冲区获得增益,我同意1是最佳选项 但是,我们可以说,除了写入/读取通道引起的隐式锁定和解锁之外,不需要其他重要的go例程切换。然后

我在上面读到,一个应该使用最多1个通道长度

虽然我很清楚,使用100或1000的通道大小是非常糟糕的做法,但是我想知道为什么10的通道大小不是一个有效的选择。为了得出正确的结论,我遗漏了一些部分

在下面,您可以使用我的参数和一些基准测试支持的反参数

我理解,如果负责从该通道写入或读取的两个go例程在顺序写入或从该通道读取的过程中被其他IO操作中断,则无法从更高的通道缓冲区获得增益,我同意1是最佳选项

但是,我们可以说,除了写入/读取通道引起的隐式锁定和解锁之外,不需要其他重要的go例程切换。然后,我将得出以下结论:

在使用大小为1和10 GR=go例程的通道缓冲区处理通道上的100个值时,请考虑上下文切换的数量

缓冲区=1:GR1插入1个值,GR2读取1个值X 100~200个go例程开关 缓冲区=10:GR1插入10个值,GR2读取10个值X 10~20个go例程开关 我做了一些基准测试来证明这实际上更快:

package main

import (
    "testing"
)

type a struct {
    b [100]int64
}

func BenchmarkBuffer1(b *testing.B) {
    count := 0
    c := make(chan a, 1)
    go func() {

        for i := 0; i < b.N; i++ {
            c <- a{}
        }
        close(c)
    }()
    for v := range c {
        for i := range v.b {
            count += i
        }
    }
}

func BenchmarkBuffer10(b *testing.B) {
    count := 0
    c := make(chan a, 10)
    go func() {

        for i := 0; i < b.N; i++ {
            c <- a{}
        }
        close(c)
    }()
    for v := range c {
        for i := range v.b {
            count += i
        }
    }
}
然而,如果我每读10遍就加上一次睡眠时间,就不会产生更好的效果


import (
    "testing"
    "time"
)

func BenchmarkBuffer1WithSleep(b *testing.B) {
    count := 0
    c := make(chan int, 1)
    go func() {
        for i := 0; i < b.N; i++ {
            c <- i
        }
        close(c)
    }()
    for a := range c {
        count++
        if count%10 == 0 {
            time.Sleep(time.Duration(a) * time.Nanosecond)
        }
    }
}

func BenchmarkBuffer10WithSleep(b *testing.B) {
    count := 0
    c := make(chan int, 10)
    go func() {
        for i := 0; i < b.N; i++ {
            c <- i
        }
        close(c)
    }()
    for a := range c {
        count++
        if count%10 == 0 {
            time.Sleep(time.Duration(a) * time.Nanosecond)
        }
    }
}
仅供参考:我还用一个CPU再次进行了测试,得到了以下结果:

BenchmarkBuffer1                 5831193               207 ns/op
BenchmarkBuffer10                6226983               180 ns/op
BenchmarkBuffer1WithSleep         556635             35510 ns/op
BenchmarkBuffer10WithSleep        984472             61434 ns/op
cap 500频道绝对没有问题,例如,如果该频道用作信号灯

您阅读的样式指南建议不要使用cap 64的缓冲通道,因为这看起来是一个不错的数字。但是这个建议不是因为性能!顺便说一句:你们的微基准是无用的微基准,它们不衡量任何相关的东西

无缓冲通道是某种同步原语,对我们非常有用

缓冲通道可以在发送方和接收方之间进行缓冲,这种缓冲对于观察、调优和调试代码来说是有问题的,因为创建和使用会进一步解耦。这就是为什么《样式指南》建议使用无缓冲通道,或者最多使用1的上限,因为这有时是正确性所必需的

它也不禁止更大的缓冲帽:

任何[0或1]以外的尺寸都必须经过高度审查。考虑大小是如何确定的,是什么阻止信道在负载和阻塞写入器上填充,以及当发生这种情况时会发生什么。[我的皇帝]

如果您能解释为什么是27而不是22或31,以及这将如何影响程序行为而不仅仅是性能,那么您可以使用27的上限!如果缓冲区已满

大多数人高估了业绩。正确性、操作稳定性和可维护性是第一位的。这就是本风格指南的内容。

cap 500频道绝对没有问题,例如,如果该频道用作信号灯

您阅读的样式指南建议不要使用cap 64的缓冲通道,因为这看起来是一个不错的数字。但是这个建议不是因为性能!顺便说一句:你们的微基准是无用的微基准,它们不衡量任何相关的东西

无缓冲通道是某种同步原语,对我们非常有用

缓冲通道可以在发送方和接收方之间进行缓冲,这种缓冲对于观察、调优和调试代码来说是有问题的,因为创建和使用会进一步解耦。这就是为什么《样式指南》建议使用无缓冲通道,或者最多使用1的上限,因为这有时是正确性所必需的

它也不禁止更大的缓冲帽:

任何[0或1]以外的尺寸都必须经过高度审查。考虑大小是如何确定的,是什么阻止信道在负载和阻塞写入器上填充,以及当发生这种情况时会发生什么。[我的皇帝]

如果您能解释为什么是27而不是22或31,以及这将如何影响程序行为而不仅仅是性能,那么您可以使用27的上限!如果缓冲区已满


大多数人高估了业绩。正确性、操作稳定性和可维护性是第一位的。这就是本样式指南的内容。

使用大通道缓冲区有问题的一个例子:您不想在通道上发送数据时被阻塞,所以您给它一个足够大的缓冲区,这样它就不会被填满。对于某些操作,大小为10的通道是一个非常有效的选择。事实上,它是某些操作的唯一选项。使用大通道缓冲区有问题的一个例子:您不希望通道上的发送永远阻塞,因此您给它一个足够大的缓冲区,以便它永远不会被填满。对于某些操作,大小为10的通道是一个完全有效的选项。事实上,这是一些手术的唯一选择
在沃尔克,nks有很多。这就清楚了。非常感谢@Volker。这就清楚了。
BenchmarkBuffer1WithSleep-12              856886             53219 ns/op
BenchmarkBuffer10WithSleep-12             929113             56939 ns/op
BenchmarkBuffer1                 5831193               207 ns/op
BenchmarkBuffer10                6226983               180 ns/op
BenchmarkBuffer1WithSleep         556635             35510 ns/op
BenchmarkBuffer10WithSleep        984472             61434 ns/op