老板花重金买了台 128 核服务器,我的 Go 程序反而变慢了?

老板花重金买了台 128 核服务器,我的 Go 程序反而变慢了?

💡 原文中文,约4300字,阅读约需11分钟。
📝

内容提要

在超多核时代,Go语言的并发模型受到NUMA架构和GC的性能瓶颈影响,尽管核心数增加,程序吞吐量未线性增长。Go团队计划通过优化调度和内存分配来提升性能。

🎯

关键要点

  • 在超多核时代,Go语言的并发模型受到NUMA架构和GC性能瓶颈影响。

  • 尽管核心数增加,程序吞吐量未线性增长,甚至P99延迟变高。

  • Go的GMP调度模型在小几十核机器上表现良好,但在128核机器上亲和性被撕裂。

  • GC导致的STW(Stop The World)使得调度器在恢复后分配P给任意空闲的M,造成Cache Miss。

  • NUMA架构下,CPU访问本地内存快,跨大区访问延迟高,Go语言目前是非NUMA感知的。

  • Go的工作窃取算法在NUMA时代变得低效,导致内存访问延迟增加。

  • Go团队计划通过优化调度和内存分配来提升性能,解决超高核数和NUMA下的性能瓶颈。

  • Go 1.25和1.26已带来部分改进,NUMA感知的内存分配等优化在后续版本中规划。

  • 开发者需理解代码在真实硬件和操作系统上的物理足迹,避免盲目增加机器。

  • 在高并发服务性能退化时,检查NUMA命中率,考虑使用runtime.LockOSThread()等方法。

🔎

延伸解读

NUMA架构的挑战

在超多核的环境中,NUMA架构带来的内存访问延迟显著影响了Go程序的性能。开发者需要关注内存分配的NUMA亲和性,避免跨节点的内存访问,以减少延迟和提高吞吐量。

GC对性能的影响

Go语言的垃圾回收(GC)机制在高并发场景下可能导致性能下降,尤其是在多核处理器上。开发者应考虑GC的停顿时间对程序的影响,并探索优化调度和内存分配的方法,以提升整体性能。

未来的优化方向

Go团队正在积极解决超高核数和NUMA架构下的性能瓶颈,未来版本将引入NUMA感知的内存分配等优化。开发者应关注这些更新,以便在新版本发布后及时调整代码,提升应用性能。

延伸问答

为什么我的Go程序在128核服务器上反而变慢了?

Go程序在128核服务器上变慢的原因主要是NUMA架构和GC性能瓶颈,导致吞吐量未线性增长,P99延迟反而增加。

NUMA架构对Go程序性能有什么影响?

NUMA架构使得CPU访问本地内存快,但跨大区访问延迟高,Go语言目前是非NUMA感知的,导致内存访问效率低下。

Go团队如何计划解决超高核数下的性能瓶颈?

Go团队计划通过优化调度和内存分配,增强NUMA感知,修复调度器的亲和性问题,以提升性能。

在高并发服务中,如何检查NUMA命中率?

可以使用top和numastat命令来检查NUMA命中率,以评估内存访问的效率。

Go的GMP调度模型在多核机器上表现如何?

在小几十核机器上,Go的GMP调度模型表现良好,但在128核机器上,亲和性被撕裂,导致性能下降。

Go 1.25和1.26版本带来了哪些改进?

Go 1.25和1.26版本带来了部分改进,包括容器感知的GOMAXPROCS和Green Tea GC等优化。

🏷️

标签

➡️

继续阅读