为了账号安全,请及时绑定邮箱和手机立即绑定

golang 通道 vs. 常规生成以提高性能

golang 通道 vs. 常规生成以提高性能

Go
凤凰求蛊 2021-12-07 17:19:52
我很好奇是否有人分析过这两种范式之间的性能差异。有一个侦听器 goroutine(可能是几个),它侦听套接字并生成一个新的 goroutine 来处理该信息并将其发送到它必须去的任何地方。在发送命令之后,例程将完成并被销毁。每个请求都会创建一个例程,然后在完成后销毁它。有一个侦听器 goroutine(可能是几个)来侦听套接字并将数据传递到通道。许多 goroutine 阻塞在一个通道接收上,并且会轮流从通道中取出东西并处理它们。完成后,例程将在通道上等待以获取更多信息。在这种范式中,例程永远不会被破坏。几个主例程在通道上接收套接字信息,其他例程在通道上等待处理信息。惯例永远不会被破坏。我的问题是对于在接收中接收大量小信息的系统(每条消息 0.5-1.5kb)但同时有大量消息传入(大容量,小尺寸)什么范式对速度和加工。有一堆例程坐着并使用频道将它们分散到一堆聆听例程中?或者,为每个请求创建一个路由并在每个请求后结束该例程?即使是基本的意识形态和猜想也很酷。
查看完整描述

1 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

一般来说,我倾向于发现生成无数例程而不重用它们是浪费:即使 goroutines 便宜,但它们不是免费的,并且意味着调度成本。

现在,这两种方法在高负载下都有缺点:生成例程会消耗您的内存、调度,并可能使您的程序停止运行,而使用通道时,您的请求将挂起,直到处理前一个。

我通常的方法是做一个基于批处理的管道(灵感来自优秀的Go Concurrency Patterns: Pipelines and cancels博客文章):

  • 侦听器在通道中发送请求

  • 一个聚合例程将请求放入缓冲区

  • N 个处理例程在空闲时请求缓冲区块

这样您就可以精确控制管道的流程和行为,同时保持多个工作人员的优势。如果缓冲区超过限制大小、产生或杀死新工作人员以适应负载等,您可以通过丢弃传入请求来轻松实现溢出机制。


查看完整回答
反对 回复 2021-12-07
  • 1 回答
  • 0 关注
  • 196 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信