Go Runtime

Go Runtime 记录一些 Go Runtime 的设计点

调度

内存

GC

优化经验

  • 协程池的重要性远没有 Java,CPP 中线程池那么重要
    • 协程的生成不涉及系统调用,需要的栈资源也很少
    • P 和全局都做了 dead G 的缓存
    • 如果协程池实现的不好,反而因为锁影响了性能
    • 对于并发控制、保护资源,完全可以选择其他方式
  • 什么时候需要协程池?

    • 主要用于减少栈扩容和缩容,有些场景下栈扩容和缩容消耗较多 CPU(可用 pprof 查看 morestack),比如长连接
    • 大量维持连接的协程可以不用扩容栈,复杂任务交给任务携程处理,此类携程的数量比较少
  • 利用 sync.Pool 对于频繁分配的堆上对象,可以使用 sync.Pool,减少分配频次,进而降低 GC 频率

  • 一点点拷贝胜过指针 如果对象较小,可以考虑用栈上对象+传参的方式实现,这样可以减少 GC 对 CPU 消耗

  • slice 和 map 如果提前知道容量范围,可以初始化一个合适的容量,减少扩容

  • 用 json-iterator 替换 encoding/json 减少反射的使用,提高效率

  • 方便的 pprof 工具
    • https://github.com/google/gops
    • 可以很方便的内嵌入服务中,并可以在线查看 pprof 信息