这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记
讲师介绍与课程回顾介绍
两个方面的优化
对go底层需要解决通用的性能问题
需要用数据驱动的方法来解决性能问题
首先优化最大瓶颈
主要写go SDK,右下角的图,把GoSDK分成接口方面,api和接口优化的新的API,实现部分有编译器,调度器,gc等,保证接口稳定的情况下去做
go要用更多的测试用例去覆盖场景,确定优化没有问题。
隔离性指的是,选项是否开启这个优化,如果不开启是和之前一样的,保证稳定性
开启优化需要日志输出
自动内存管理
概念
程序运行根据需求分类的内存,比如malloc,自动的花就由程序运行时系统管理的动态内存
自动内存管理叫垃圾回收,连续释放两次内存,用了又去使用的问题,会导致正确性和安全性
内存使用方面使用垃圾回收会有效果,核心任务如上
从runtime里面看到的
看一下专业名字
进程里不同线程不一样的介绍,用户启动的线程,和用户启动的go routine都属于业务线程
parallel,并行,那就是多个
concurrent,串行的,一边gc,一遍做业务
第一张图,是gc之前没有标记到,在做标记回收的时候,一个新的对象b由y指向,但是b还没有标记,需要CGC需要把b也标记成存活,collectors必须要感受到对象指向关系
Tracing garbage collection
标记灰色为活着的,把存活复制
标记清理,将死亡对象进行内存分配
压缩
generational GC (一种管理gc的方式)
注意分代假说,函数里new一堆对象,返回后里面创建的就死掉了
吞吐率指花了多少时间做GC
老年代趋与一直或者,反复复制开销较大,使用mark sweep做
需要根据对象的周期来处理
reference counting(另一种)
蓝色圈圈是引用对象,数字表示引用的计数,被清理后就都清理了
o的引用计数就1
o的引用计数就变成2
清0就可以被释放了
可以看到程序一遍执行,一遍在进行辣鸡管理,处理内存
同时不需要了解runtime细节,只要计数即可,一些库就可以做这种处理,例如c++智能指针
智能追踪和runtime耦合很高
原子操作比较有问题,同时环形操作如下图,不能回收
如图null的时候大的数据结构也有问题
总结
Go内存管理和优化(主要是堆上的分析,对于栈要逃逸分析)
Go内存分配
Go 内存管理构成了多级缓存机制,从 OS 分配得的内存被内存管理回收后,也不会立刻归还给 OS,而是在 Go runtime 内部先缓存起来,从而避免频繁向 OS 申请内存。内存分配的路线图如下。
分层使用缓存,从go routine分配,在p上有数据结构,根据对象大小找到mspans,如果mspan满了,就在mcentral找到填到mspans即可
很多时候是分配小对象
需要对对象分配做优化
优化方案,balanced GC
三个指针维护GAB,可以在GAB上做指针对撞操作不需要去做之前的流程,直接返回创建大小的指针即可
对象分配进行分析,针对小对象就可以有优化思路
用copy gc来管理小对象,根据对象的生命周期,就能进行清理策略
Q:g1和g2是用新的gab?
S:g1g2被回收了
Q:g用于小对象分配的noscan,如果用于大于的,按照原来的方法
修改指针的过程需要stop work
用额外的结构体来判断地址其实的空间,go的对象没有对象头
PPT里mcache管理着一组mspan,是每个级别的mspan都会有一个
编译器和静态分析
基本介绍
源代码是字符串的流,经过词法分析变成词素,然后语法分析器变成抽象语法树,对语义分析器生产结果变成decorated ast,用ir变成中间代码,然后优化和生成,主要学习编译器后端变化
数据流和控制流
根据控制流输出数据流
过程内和过程间分析
Go编译器优化
函数内联
直接把副本复制到调用函数里面,然后直接达成过程内分析,帮助优化
通过编译器参数选项选择inline还是不inline
可以看到优化的效果了
不好放到icache里面,会产生icachemiss
内联一般是好的,但是如果是递归还是什么的,会导致Go镜像变大,编译器会调动策略来做调整
Beast Mode go编译器优化的成品
逃逸分析
被其他函数访问到了,那就是逃逸了,反之没有逃逸
多内联使得不逃逸,可以在栈上分配,从而降低gc负担
beast mode 在栈上使用降低了内存使用率
主要是对内存和编译器优化
Q&A
Q:mutator和go routine 关系
A:理解为一致
Q:代码循环引用监测发现
A:用weak reference抓住这种特性进行回收
Q:GO语言GC的过程
A:第一是扫描go routine过程,然后暂停,最后清理的时候也有一个暂停
Q:mspan用完会怎么样
A:假设用完了,就找mcentral的空余块填充,依次往下
A:mspan 是一样大的
A:micro -benchmark 是一个基准的程序,优化会不会有结果,用gotest做的,就能得到结果
Q:内联问题
A:编译根据策略要不要inline进来
A:做清理看mark的块置1或者0
Q:scan类型的为什么不在GAB上分配?
A:如果有扫描着的对象就不好对其分配,在内存被延迟释放。用并行进行清楚解决方法??不是太理解
Q:并发清除怎么解决?
A:新生成就变成黑色,做GC分配时,就不会漏掉了
Q:gmp里的g上面讲过了