这篇文章解释了为什么在 Go 1.24 版本中,你的程序可能因为 map 变慢了,以及 Go 团队是怎么计划修复这个问题的。
Golang 1.24 中最吸引我的功能就是 SwissMap,在以前的非官方实现中,有些场景能够提升50% 的性能,官方的实现中,也有不小的性能提升。 详情参考我以前的文章: SwissTable会成为Golang标准map的实现嘛?
但是 如果你在使用 Go 1.24 时可能会发现SwissMap 没有达到预期的表现,甚至程序运行变慢了,特别是在 Map很大的时候,这不是你的幻觉,确实存在这个问题。![[Pasted image 20250520195831.png]] https://x.com/valyala/status/1879988053076504761[1]
这个问题记录在 Issue #70835[2] 中,开发者们正在努力解决它。
Go 的 map 在新版中使用了Swiss Table,它在小 map 和高并发的场景下非常快。但是当 map 很大、数据又不在 CPU 缓存里(也就是说,数据是“冷”的),就会变慢。
为什么会这样呢?
因为 SwissMap 的内部结构比较复杂,它会分几层来存储数据:
当你查找一个 key 的时候,可能需要进行 4 到 6 次跳转,每一次都可能遇到缓存未命中。这样就会导致 CPU 忙着从内存取数据,速度就慢了。
像 Prometheus 这样的大型项目就发现了这个问题。他们升级到 Go 1.24 后,CPU 使用率上升了很多,经调查发现就是因为 map 的查找变慢了。
问题并不是在测试用例里发现的,而是在真实的线上场景中出现的。
Go 团队的工程师 Michael Pratt 通过做很多测试,找到了 map 访问变慢的原因,并在 Issue #70835[2] 中详细说明。
为了让 map 更快,他们计划做以下几件事:
这些改动并不简单,因为会影响到 Go 的运行时核心:
这个问题被广泛讨论和跟踪,可以通过Issue #70835[2] 了解更多的 细节。 Go Release Dashboard[3] 中已经标记这个问题将会在 Go1.25 中解决 此外 Issue #71368[4] 中也讨论了 另一个与内存布局的问题。
Go 团队一直在努力让语言运行得更快更稳。SwissMap 是个好改进,但它也带来了新挑战,比如这次的冷缓存性能下降。 Issue #70835 展示了 Go 是如何通过社区反馈不断进步的。感谢像 Prometheus 这样的开源项目,他们的报告帮助 Go 做得更好。 如果一切顺利,Go 1.25 就能把速度和稳定性都带回来。 我们一起期待吧!
[1]https://x.com/valyala/status/1879988053076504761
[2]Issue #70835: https://github.com/golang/go/issues/70835
[3]Go Release Dashboard: https://github.com/golang/go/milestone/122
[4]Issue #71368: https://github.com/golang/go/issues/71368