青训营X豆包MarsCode 技术训练营第六课 | 豆包MarsCode AI 刷题

23 阅读4分钟

性能优化指南

Go语言提供了支持基准性能测试

性能表现需要实际数据衡量

Go语言提供了支持基准性能测试的benchmark工具

 go test -bench=, -benchmem

性能优化建议——Slice

比如说在创建切片的时候提前分配内存,这样可以减少内存分配的次数

切片的实现原理: 切片里面带有指针长度,还有容量,当容量没有满的时候,就直接添加进去,然后增加长度,但是当容量满了的时候,就要给这个数组做一个扩容,很麻烦

就是扩容的本质还是使用原来的数组

另一个陷阱:假如创建新的数组,只引用了原来数组的几个元素,那么原来数组里面的其他元素就没办法释放,造成资源浪费,所以使用copy代替slice

当map使用的时候最好也用预分配做一个处理,他的扩容机制和切片很像

字符串拼接的时候,直接使用加号的性能是最差的,可以使用strings.Builder或者bytes.Buffer来进行拼接,

因为字符串在go语言中,是不可变的类型,每次拼接需要重新分配内存,但是上面两种方式的实现方式都是byte数组,拼接的时候,就是扩容,不用重新分配内存

  • 避免常见的性能陷阱可以保证大部分程序的性能
  • 普通应用代码,不要一味的追求程序的性能
  • 越高级的性能优化越容易出现问题
  • 满足正确可靠,简介清晰的质量要求的前提下提高程序性能

pprof测试工具

基本使用方法

性能调优原则:

要依靠数据而不是猜测

要定位最大瓶颈,而不是细枝末节

不要过早优化

不要过度优化

会把函数调用都显示出来,并且生成函数链,这样就可以直观地看到使用了哪些函数,并且函数的执行顺序是怎样的

可视化执行指令,并且执行之后会在浏览器上面显示执行效果

pprof—采样过程和原理

采样对象:函数调用和他们占用的时间

采样率:100/秒,固定值

采样时间:从手动启动到手动结束

操作系统

每10ms向进程发送一次SIGPROF信号

进程

每次接收到SIGPROF信号会记录调用堆栈

写缓冲

每100ms读取已经记录的调用栈写入输出流

其实里面最后输出的记录由两部分组成:

第一部分就是:进程的执行时间

第二部分就是:已经记录的调用栈里面的一些信息

采样程序通过内存分配器在堆上分配和释放内存,记录分配/释放的大小和数量

采样率:每分配512KB记录一次,可在运行开头修改,1为每次分配记录

采样时间:从程序运行开始到采样时

采样指标:alloc_space , alloc_object ,inuse _space ,inuse_objects

计算方式:inuse = alloc - free

是不是要是效率比较差的时候,调用的函数就会少,堆里面的东西就少,虽然每100ms记录一次,但是实际记录的函数是比较少的,这样就是固定时间来比较调用函数的数量

采样阻塞操作的次数和耗时:超过阈值才会被记录,每次加一

采样抢夺所的次数,只有固定比例的锁操作,才会被记录,每次加一

性能调优案例

不同的参数可能会执行不同的方法

从各个维度来评估

每个机器的性能都是不一样的

日志的使用要规范一些,否则会出现很多没用的日志

高并发场景优化不足

就是高峰期和平常的需求量不同,需要优化一下,提高项目的瓶颈

通过返回值来判断优化是否正确:记录之前的返回值,优化之后在记录一次,进行比较