Go内存管理及性能与编译优化 | 青训营笔记

45 阅读3分钟

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

1.性能优化

由于自顶向下的是业务代码、SDK、基础库、语言运行时以及OS,所以性能优化有着针对不同层面的优化。

(1)业务层优化

针对特定场景,具体问题,具体分析

容易获得较大的性能收益

(2)语言运行时优化

解决更通用的性能问题

考虑更多场景

(3)数据驱动

自动化性能分析工具——pprof

依靠数据而非猜测,实事求是

首先优化最大瓶颈

2.自动内存管理

(1)概念

动态内存:程序在运行时根据需求动态分配的内存:类似于C语言的malloc()

自动内存管理:由程序语言的运行时系统管理动态内存

(2)追踪垃圾回收

对象被回收的条件:指针指向关系不可达的对象

(3)分代GC

分代假说:most objects die young

每个对象都有年龄:经历过GC的次数

目的:对年轻和老年的对象,指定不同的GC策略,降低整个提内存管理的开销

不同年龄的对象处于heap的不同区域

年轻代:常规的内存分配,由于存活对象很少,可以采用copying GC,GC吞吐率很高

老年代:对象趋向于一直活着,反复复制开销较大,可以采用mark-sweep GC

(4)引用计数

每个对象都有一个与之关联的引用数目

3.内存管理及优化

(1)分块

提前为对象在heap上分配内存

(2)缓存

TCMalloc:thread caching

缓存过程:每个p包含一个mcache用于快速分配,用于g分配对象,mcache管理一组mspan,当mcache中的mspan分配完毕,向mcentral的mspan,当mspan中没有分配的对象,mspan会被缓存在mcentral中

(3)内存管理优化

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

空间较小的对象占比比较高

Go内存分配比较耗时

4.静态分析

(1)控制流和数据流

静态分析 :不执行程序代码,推导程序的行为,分析程序的性质。

控制流:程序执行*流程

数据流:数据在控制流上的传递

(2)过程内分析

仅在函数内部进行分析

(3)过程间分析

考虑过程调用时参数传递和返回值的数据流和控制流

5.编译器优化

(1)思路

场景:面向后端长期执行任务

Tradeoff:用编译时间换取更高效的机器码

(2)函数内联

将被调用函数的函数体(callee)的副本替换到调用位置(caller)上,同时重写代码以反映参数的绑定

(3)Beast Mode

调整函数内联的策略,使更多函数被内联

降低函数调用的开销

增加了其他优化机会:逃逸分析