专栏名称: 码小辫
给程序员和编程爱好者分享计算机编程电子书以及相关的学习资源
目录
相关文章推荐
直播海南  ·  两名干部因买方便面被通报?官方回应 ·  18 小时前  
直播海南  ·  湖南烟花厂爆炸已致9人遇难、26人受伤 ·  昨天  
直播海南  ·  烟花厂爆炸最新消息:2人失联,9人受伤 ·  2 天前  
51好读  ›  专栏  ›  码小辫

Go1.24 Map 引入了新的问题,预计将在 Go1.25 修复!

码小辫  · 公众号  ·  · 2025-05-08 17:10

主要观点总结

文章介绍了Go语言在1.24版本中Map的新特性及其带来的性能提升,同时也指出了新特性引发的问题点,包括map[int64]struct{}的槽空间占用问题以及可能对CPU的影响。文章还讨论了解决此问题的不同布局方式,包括键/值一起存储和所有键集中存储的对比,以及社区对此问题的反馈。最后,文章提到这个问题有望在Go1.25中得到解决或缓解,并给出了参考资料。

关键观点总结

关键观点1: Go语言在1.24版本中对Map进行了改进,使用了Swiss Table替换Hashmap的原始实现,带来了性能提升。

使用Swiss Table作为Map的底层数据结构,带来了显著的综合性能提高。

关键观点2: 在Go1.24新引入的Map特性中,发现了一个问题点:map[int64]struct{}的槽空间占用问题。

每个槽(slot)需要16字节空间,而不是预期的8字节。这是因为Map内部定义存储方式的副作用以及struct大小规则导致的。

关键观点3: 问题点引发了社区的关注,有开发者提出了解决方案,涉及更改布局以优化缓存未命中的问题。

对比了键/值一起存储和所有键集中存储两种布局方式的优缺点,并讨论了控制字的作用。

关键观点4: 社区反馈显示,在Go1.24中map[uint64]struct{}的性能比Go1.23低10%。

具体表现在Prometheus项目中,使用Go1.24时访问大Map会消耗更多的CPU。

关键观点5: 目前这个问题点有望在Go1.25中得到解决或缓解。

文章提到软件设计没有银弹,选择了一种方案就可能会有另一种方案的短板。


正文

请到「今天看啥」查看全文


是日常中用来占位表现最为常用的一个用法之一。

原因

造成这个现象的原因在于 Map 内部定义存储 [1] 方式的所造成的副作用:

  type group struct {
      ctrl uint64
      slots [abi.SwissMapGroupSlots]struct {
          key  keyType
          elem elemType
      }
  }

原因在于:

  • elemType struct{}
    • Go 编译器中的 struct 大小规则规定,如果 struct 以零大小(zero-size)类型结束,则该字段将获得 1 字节的空间。
    • 会设计这个机制的目的是:防止有人创建指向最后一个字段的指针,Go 编译器不希望指针指向分配结束的位置。
  • keyType 需要 8 字节对齐。

划重点:最后一个字段 keyType 实际上使用了整整 8 字节,这是 KVKVKVKV(K/V 一起存储) 由于对齐要求而浪费空间的最极端情况。

这个问题出现在了新的 Map 新引入的 swissmaps 中。

解决思路

实际上还是 @Michael Pratt,既发现问题,还提出如何解决问题。简直是专业的大好人!其提出了新的 issues《 runtime: map cold cache improvements [2] 》:







请到「今天看啥」查看全文