高性能Go语言发行版优化与落地实践|青训营笔记9

63 阅读3分钟

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

image.png

前言

  • 上节课:高质量编程与性能调优
  • 高质量编程:
    • 编码规范:写出高性能、可维护的代码
    • 性能优化建议
  • 性能优化
    • 分析工具——pprof:采样原理、如何定位性能问题等等
    • 业务优化
    • 基础库优化
    • Go语言优化
  • 本节课:高性能Go语言优化与落地实践
  • 优化
    • 内存管理优化
    • 编译器优化
  • 背景
    • 自动化内存管理和Go内存管理机制
    • 编译器优化的基本问题和思路

1.自动内存管理

动态内存

  • 程序在运行时根据需求动态分配的内存: malloc()

自动内存管理(垃圾回收) :由程序语言的运行时系统管理动态内存

  • 避免手动内存管理,专注于实现业务逻辑
  • 保证内存使用的正确性安全性: double -free problem, use- after-free problem

image.png

三个任务

  • 为新对象分配空间
  • 找到存活对象
  • 回收死亡对象的内存空间

1.1 自动内存管理

● Mutator:业务线程,分配新对象,修改对象指向关系

● Collector: GC线程,找到存活对象,回收死亡对象的内存空间

● Serial GC:只有一个collector

● Parallel GC:支持多个collectors同时回收的GC算法

●Concurrent GC: mutator(s)和collector(s)可以同时执行

  • Collectors必须感知对象指向关系的改变!

2.1 评价GC算法 安全性(Safety):不能回收存活的对象基本要求

  • 吞吐率(Throughput): 1 GC时间/程序执行总时间GC时间/程序执行总时间 花在GC.上的时间

  • 暂停时间(Pause time): stop the world (STW)业务是否感知

  • 内存开销(Space overhead) GC元数据开销

追踪垃圾回收(Tracing garbage collection)

引用计数(Reference counting)

2.Go内存管理及优化

2.1Go内存分配 目标:为对象在heap.上分配内存

提前将内存分块

  • 调用系统调用mmap()向OS申请一大块内存, 例如4 MB
  • 先将内存划分成大块,例如8 KB,称作mspan
  • 再将大块继续划分成特定大小的小块,用于对象分配
  • noscan mspan:分配不包含指针的对象 GC不需要扫描
  • scan mspan:分配包含指针的对象 GC需要扫描

对象分配:根据对象的大小,选择最合适的块返回

image.png

2.2Go内存管理优化

对象分配是非常高频的操作:每秒分配GB级别的内存

小对象占比较高

Go内存分配比较耗时

●分配路径长: g -> m-> p-> mcache -> mspan -> memory block -> return pointer

●pprof:对象分配的函数是最频繁调用的函数之-

2.3 Balanced GC ●GAB对于Go内存管理来说是一个对象

●本质:将多个小对象的分配合并成一次达对象的分配

●问题: GAB的对象分配方式会导致内存被延迟释放

方案:移动GAB中存活的对象

·当GAB总大小超过一定阈值时, 将GAB中存活的对象复制到另外分配的GAB中

·原先的GAB可以释放,避免内存泄漏

·本质:用copying GC的算法管理小对象。根据对象的生命周期,使用不同的标记和清理策略

image.png