编写高性能Go代码的最佳实践

19-05-07 banq
         

本文档概述了编写高性能Go代码的最佳实践。点击标题进入中文页面,分为几个部分:

1) 编写高性能软件的基本技巧
  * CS 101-level的东西
2) 编写快速软件的技巧
  * 关于如何从Go获得最佳效果的Go-specific章节
3) 编写*真正*快速软件的高级技巧
  * 当你优化的代码不够快时

何时何地做优化?

过早的优化是万恶之源,在绝大多数情况下,程序的大小和速度不是问题。最简单的优化不必这样做。第二个最简单的优化就是购买更快的硬件。

如何优化

任何可以测量的东西都可以优化。确保你正在衡量正确的事情。

如果目标是改进CPU,那么什么是可接受的速度。你想要将当前的性能提高2倍吗?10倍?你能否说它是“小于时间T的大小为N的问题”?你想减少内存使用量吗?多少钱?对于内存使用情况的变化,可以接受的速度有多慢?你愿意放弃什么来换取较低的空间需求?

本书主要讨论如何减少CPU使用率,减少内存使用量并减少延迟。很高兴指出你很少能做到这三点。

数据的更改

增加数据结构的想法:

  • 额外字段:例如,存储链接列表的大小,而不是在询问时迭代。或者将经常需要的其他节点的指针存储到多个搜索中(例如,双向链接列表中的“向后”链接以进行删除O(1))。当你需要的数据便于存储并保持最新时,这些更改很有用。
  • 额外的搜索索引:大多数数据结构都是为单一类型的查询而设计的。如果你需要两种不同的查询类型,对数据进行额外的“查看”可能会有很大的改进。例如,[] struct,由ID引用,但有时是string - > map [string] id(或* struct)
  • 有关元素的额外信息:例如布隆过滤器。这些数据结构必须小而快,以免压倒其余的数据结构。
  • 如果查询很昂贵,请添加一个缓存。我们都熟悉memcache,但还有进程内缓存。

  • 通过网络,网络+序列化成本将会受到影响
  • 进程内缓存,但现在你需要担心到期
  • 即使是单个项目也可以帮助(日志文件时间解析示例)

算法的更改

如果你不更改数据,另一个主要选项是更改代码。最大的改进很可能来自算法变化。O(n)效率问题。

基准输入

编写好的基准测试可能很困难。

程序调整

程序调优曾经是一种艺术形式。

Go编译器在匹配gcc和clang方面还有很长的路要走,但这确实意味着在调整时需要小心,特别是在升级Go版本时不要变得更糟。一旦编译器得到改进,肯定会出现一些针对缺少特定编译器优化工作的调整。

​​​​​​​