这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记。
用于记录Go语言原理与实践课程的部分笔记。
一、Go性能优化与落地
性能优化的层面有三大部分:业务优化(针对场景,性能收益较大)、语言运行时优化(考虑更多场景,解决更通用的问题)和数据驱动(pprof)
实现:做Go SDK开发,分为接口和实现,并保证不影响旧功能
1、自动内存管理
(1)概念
动态内存:根据需求动态分配的内存(malloc)
GC:垃圾回收,自动内存管理,由程序语言的运行时系统管理动态内存,保证内存使用的正确性和安全性,更关注业务逻辑。任务:为新对象分配内存,找到存活对象,回收死亡对象的空间。
mutator:业务线程,分配新对象,修改对象指向关系
collector:GC线程,找到存活对象(包括已标记对象指向的对象),回收死亡对象的内存空间,要感知对象指向关系的改变
serial GC:只有一个collector
parallel GC:多个collector同时回收
concurrent GC:mutators和collectors可以同时执行
(2)追踪垃圾回收
过程:标记根对象->找到可达对象->清理不可达对象
策略:
[1]copying GC:将对象复制到另外的空间
[2]mark-sweep GC:将死亡对象的内存空间用free list管理,标记为“可分配”
[3]compact GC:原地整理,移到一起
(3)分代GC
每个对象有年龄,即经历过GC的次数,不同年龄放在heap的不同区域。
年轻代:存活对象少,GC吞吐率高,可用copying GC
老年代:趋于一直存活,可用mark-sweep GC
(4)引用计数
对象有一个与之关联的引用数目,当且仅当引用数大于0,对象存活
类似C++智能指针,但维护开销较大(原子操作),无法处理环形数据结构
2、内存管理及优化
(1)内存分配:为对象在heap上分配内存,有多层缓存
调用mmap()向OS申请内存一大块内存->将内存分成大块mspan->再将大快分为小,用于分配
mspan分为noscan(分配不包含指针的对象)和scan(分配包含指针的对象,GC要扫描,找出对象指向的对象)两类
(2)管理优化
分配路径过长,耗时高
优化方法:balanced GC
每个g绑定一个1KB内存的块GAB,存noscan类型小对象
用三指针维护GAB:top、size、end
定时清理GAB,避免单一存活对象影响GAB的回收
3、编译器和静态分析
静态分析
包括分析控制流(程序执行的流程)和数据流(数据再控制流上的传递)
过程内分析:过程(函数)内部分析
过程间分析:考虑过程调用时参数传递和返回值的数据流和控制流
4、Go编译器优化
(1)特点
用户无感知,重新编译即可获得性能收益,优化通用
用编译时间换取更高效的机器码
(2)beast mode
函数内联:将被调用函数的函数里的副本替换到调用位置上,同时重写代码以反映参数的绑定。
消除了函数调用的开销(传递参数、保存寄存器),编译时间++,Go镜像++
过程间分析->过程内分析
beast mode调整了内联的策略,使更多函数被内联,更多对象不逃逸
逃逸分析:分析指针的动态作用域,指针可被访问的作用域
指针p传递给到作用域s外,则p逃逸出s
未逃逸的对象可以在栈上分配(速度快,减少heap上的分配,降低GC负担)
二、设计模式之 Database/SQL 与 GORM 实践
实践+文档为主 惯例约束
混沌工程:是一种提高技术架构弹性能力的复杂技术手段。用于发现系统未知的脆弱一面.