我正在构建一个使用"工作池"的Golang应用程序。 goroutines,最初我开始创建一些工作池。我想知道多核处理器中的最佳工作数是多少,例如在具有4个内核的CPU中?我目前正在使用以下方法:
list
完整的实施在
之下job.NewWorkerPool(maxWorkers) 和 module.Dispatcher.Run(jobQueue)
我使用工作池的用例:我有一个接受请求并调用多个外部API并将其结果聚合到一个响应中的服务。每次通话都可以独立完成,因为结果的顺序并不重要。我将调用分派给工作池,每个调用都以异步方式在一个可用的goroutine中完成。我的请求"一旦完成工作线程,线程就会在获取和聚合结果时继续监听返回通道。完成所有操作后,最终的聚合结果将作为响应返回。由于每个外部API调用可能呈现可变响应时间,因此某些调用可以比其他调用更早完成。根据我的理解,以并行方式进行操作在性能方面会更好,就好像以同步方式一样接一个地调用每个外部API
答案 0 :(得分:3)
示例代码中的注释表明您可能会混淆GOMAXPROCS
和工作池的两个概念。这两个概念在Go中完全不同。
GOMAXPROCS
设置Go运行时将使用的最大CPU线程数。默认为系统上找到的CPU核心数,几乎不应更改。我唯一能想到改变这种情况的方法是,如果你想明确限制Go程序因某些原因使用少于可用的CPU,那么你可以将它设置为1,例如,即使在4上运行核心CPU。这在极少数情况下应该是重要的。
TL; DR; 永远不要手动设置runtime.GOMAXPROCS
。
Go中的工作池是一组goroutine,它们在到达时处理作业。 Go中有不同的处理工作池的方法。
您应该使用多少工人?没有客观的答案。可能唯一的方法就是对各种配置进行基准测试,直到找到符合要求的配置为止。
作为一个简单的例子,假设您的工作池正在执行非常耗费CPU的事情。在这种情况下,您可能需要每个CPU一个工作程序。
作为一个更可能的例子,让我们说你的员工正在做更多的I / O限制 - 例如阅读HTTP请求或通过SMTP发送电子邮件。在这种情况下,您可以合理地处理每个CPU数十甚至数千名工作人员。
然后还有你是否应该使用工作池的问题。 Go中的大多数问题根本不需要工作池。我曾经参与过几十个生产Go程序,从来没有在其中任何一个中使用过工作池。我也写了很多次一次性使用Go工具,并且只用了一次工作池。
最后,GOMAXPROCS
和工作池相关的唯一方式与goroutines与GOMAXPROCS
的关联方式相同。来自the docs:
GOMAXPROCS变量限制了可以同时执行用户级Go代码的操作系统线程数。代表Go代码在系统调用中可以阻塞的线程数没有限制;那些不计入GOMAXPROCS限制。该软件包的GOMAXPROCS函数可以查询和更改限制。
从这个简单的描述中,很容易看出可能会有更多(可能是数十万......或更多)goroutines比GOMAXPROCS
- GOMAXPROCS
仅限制如何许多"操作系统线程可以同时执行用户级Go代码" - 目前没有执行用户级Go代码的goroutines不计数。在I / O绑定的goroutine(例如等待网络响应的那些)中,不执行代码。因此,理论上最大数量的goroutine仅受系统可用内存的限制。