性能调优
性能优化建议
- slice和map预分配空间性能会更好。
- 字符串处理
- 使用 + 拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Builder更快
- 分析
- 字符串在Go语言中是不可变类型,占用内存大小是固定的
- 使用 + 每次都会重新分配内存
- strings.Builder,bytes.Buffer底层都是[]byte数组
- 内存扩容策略,不需要每次拼接重新分配内存
- 使用空结构体节省内存
- 空结构体struct{}实例不占据任何的内存空间,可作为各场景下的占位符使用
- 节省资源
- 空结构体本身具备很强的语义,即这里不需要任何值,仅作为占位符
- 使用atomatic包
- 锁的实现是通过操作系统,属于系统调用
- atomatic操作是通过硬件实现的,效率比锁高
- sync.Mutex应该用来保护一段逻辑,而不仅仅用于保护一个变量
- 对于非数值操作,可以用atomatic.Value,承载一个interface{}
性能调优原则
- 要依靠数据不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具pprof
- 说明
- 希望知道应用在什么地方耗费了多少cpu、memory
- pprof是用于可视化和分析性能分析数据的工具
- 功能简介
- 浏览器查看指标
浏览器访问localhost:6060/debuf/pprof即可查看。 - CPU
- falt == cum,说明函数中没有调用其他函数
- flat == 0, 函数中只有其他函数的调用
- Heap-堆内存
- Goroutine泄露也会导致内存泄露
- 火焰图
- Mutex、block分析同上,把pprof后面改为mutex、block即可。
性能分析工具pprof-采样过程和原理
- CPU
- 采样对象:函数调用和它们占用的时间
- 采样率:100次/秒,固定值
- 采样时间:从手动启动到手动结束
开始采样->设定信号处理函数->开启定时器
停止采样->取消信号处理函数->关闭定时器
- Heap-堆内存
- 采样程序通过内存分配器在堆上分配和释放的内存,记录分配/释放的大小和数量
- 采样率:每分配512KB记录一次,可在运行开头修改,1为每次分配均记录
- 采样时间:从程序运行开始到采样
- 采样指标:alloc_space,alloc_objects,inuse_space,inuse_objects
- 计算方式:inuse = alloc - free
- Goroutine-协程&ThreadCreate-线程创建
- Goroutine
- 记录所有用户发起且在运行中的Goroutine(即非入口runtime开头的)runtime.main调用栈信息
- ThreadCreate
- 记录程序创建的所有系统线程的信息
- Goroutine