Go语言原理与实践 | 青训营笔记

145 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记。

用于记录Go语言原理与实践课程的部分笔记。

一、Go性能优化与落地

性能优化的层面有三大部分:业务优化(针对场景,性能收益较大)、语言运行时优化(考虑更多场景,解决更通用的问题)和数据驱动(pprof)

实现:做Go SDK开发,分为接口和实现,并保证不影响旧功能

1、自动内存管理

(1)概念

动态内存:根据需求动态分配的内存(malloc)

GC:垃圾回收,自动内存管理,由程序语言的运行时系统管理动态内存,保证内存使用的正确性和安全性,更关注业务逻辑。任务:为新对象分配内存,找到存活对象,回收死亡对象的空间。

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

collector:GC线程,找到存活对象(包括已标记对象指向的对象),回收死亡对象的内存空间,要感知对象指向关系的改变

serial GC:只有一个collector

parallel GC:多个collector同时回收

concurrent GC:mutators和collectors可以同时执行 73Z2)OZR1LZ7H~HDQA`DUK1.png

(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 实践

实践+文档为主 惯例约束

RNTFS%HD~Y)3WG)MG59$OEU.png

混沌工程:是一种提高技术架构弹性能力的复杂技术手段。用于发现系统未知的脆弱一面.