我正在尝试构建异步编解码器。我已经实现了一个可以访问缓冲的作业通道的作业调度程序
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)
是否有标准方法可以找到这些参数的最佳值,是否可以使这些值与运行代码的机器的物理设置无关?
答案 0 :(得分:1)
您始终需要进行测量以确定系统在负载下的性能。这里的好消息是你只有两个变量,它们大多是独立的,所以它很容易推理。
工作者数确定您的并发性,因此对处理进行基准测试以查看最佳并发性。通常会有许多并发进程,其上的回报会急剧下降。
频道的大小就像任何其他&#34;缓冲区&#34;在一个系统中。较大的缓冲区可以处理较大的输入峰值,但代价是可能会导致较大的延迟和内存使用。
答案 1 :(得分:0)
答案是否定的。最佳设置不仅取决于您在doWork
中运行的软件(该功能将依赖多少CPU密集和IO),还取决于您的硬件可以执行多少指令以及您的系统可以处理多少IO 。
这意味着,如果您的系统执行涉及互联网访问的活动,您的CPU有多少物理内核等等,它可能取决于您的系统安装了什么或没有安装SSD,甚至是您的带宽......
答案 2 :(得分:0)
实际上,我发现有三个缓冲区大小很重要:0,1和“发送总数的上限”。
0表示同步行为。
1给出异步行为:它在select
语句中有用default
。
发送总数的上限提供了保证非阻塞行为:您可以在没有select
的情况下发送给它,而不会冒着goroutine泄漏的风险。
其他数字可能会提供略微更好的吞吐量,但在规模上它们仍然会在包含通道内部互斥锁的缓存行上竞争,并且它们更有可能掩盖潜在的死锁和goroutine泄漏。