Go语言内存管理 | 青训营笔记

52 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

1. 性能优化是什么?

  • 提升软件系统处理能力,减少不必要的消耗,充分发掘计算的计算力。

2. 为什么要做性能优化?

  • 用户体验:带来用户体验的提升--让刷抖音更加丝滑,让双十一购物不再卡顿。
  • 资源高效利用:降低成本,提高效率--很小的优化乘以海量机器会是显著的性能提升和成本节约。

3. 性能优化的层面

业务代码、SDK、基础库、语言运行时、OS
  • 业务层优化
    • 针对特定场景,具体问题,具体分析
    • 容易获得较大性能收益
  • 语言运行时优化
    • 解决更通用的性能问题
    • 考虑更多场景
    • Tradeoffs
  • 数据驱动
    • 自动化性能分析工具--pprof
    • 依靠数据而非猜测
    • 首先优化最大瓶颈

4. 自动内存管理

  • 动态内存
    • 程序在运行时根据需求动态分配的内存:malloc()
  • 自动内存管理(垃圾回收):由程序语言的运行时系统管理动态内存
    • 避免手动内存管理,专注于实现业务逻辑
    • 保证内存使用的正确性和安全性:double-free problem,use-after-free problem
  • 三个任务
    • 为新对象分配空间
    • 找到存活对象
    • 回收死亡对象的内存空间

5. Go语言内存分配

  1. 分块
  2. 缓存

6. Go语言内存管理优化

  • 对象分配是非常高频的操作:每秒分配GB级别的内存
  • 小对象占比较高
  • Go内存分配比较耗时
    • 分配路径长:g -> m -> p -> mcache -> mspan -> memory block -> return pointer
    • pprof:对象分配的函数是最频繁调用的函数之一

7. 编译器的结构

  • 重要的系统软件
    • 识别符合语法和非法的程序
    • 生成正确且高效的代码
  • 分析部分(前端front end)
    • 词法分析,生成词素(lexeme)
    • 语法分析,生产语法树
    • 语义分析,收集类型信息,进行语义检查
    • 中间代码生成,生成 intermediate representation(IR)
  • 综合部分(后端back end)
    • 代码优化,机器无关优化,生成优化后的IR
    • 代码生成,生成目标代码

8. Go编译器优化

  • 为什么做编译器优化
    • 用户无感知,重新编译即可获得性能收益
    • 通用性优化
  • 现状
    • 采用的优化少
    • 编译时间较短,没有进行较复杂的代码分析和优化
  • 编译优化的思路
    • 场景:面向后端长期执行任务
    • Tradeoff:用编译时间换取更高效的机器码
  • Beast mode
    • 函数内联
    • 逃逸分析
    • 默认栈大小调整
    • 边界检查消除
    • 循环展开
    • ......

9. 总结

通过本节课程的学习,对于Go语言的内存管理、性能优化方面的知识点有了一定的认识。尤其是对于内存分配的分块和缓存方面的内容有着比较深刻的理解,设计的方面也是非常的高效。使得内存的利用效果大大提升。合理的分配了内存,尽量减少了不必要的内存消耗。