Go语言性能优化建议 | 青训营笔记

80 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天

首先我们要明白,性能优化的前提是满足正确可靠,简洁清晰等质量因素。其次性能是对时间和空间的综合考虑。针对go语言我们可以以下几条建议。

1.评估性能

当我们的项目需要得到性能方面的优化提升的时候,我们首先就需要依靠实际的数据来观测性能,而GO语言提供了基准测试的工具benchmark,在前面测试的文章中也介绍了。

基本命令:go test -bench.= -benchmem

结果说明:

image.png

2.slice

1.在使用slice的时候尽量按照实际的需求指定好cap容量分配一块较大的内存,减少后续程序运行时内分配带来的消耗

2.当在原来的切片上去一段小的切片,且后续只需要用到这个小的切片,那我们最好使用copy操作复制小的切片,这是因为切片操作是不会创建一个新的底层数组,也就是说共享底层的数组类似于cpp中的string_view,所以大切片上取小切片会导致底层数组一直无法被释放,就会无意中浪费很多内存。(可以使用go test -run =. -v来查看使用的内存)

说明:append引发的深思https://blog.csdn.net/bestzy6/article/details/119981699

3.map

1.跟slice类似同样是为了避免后续内存分配带来的消耗可以根据实际情况预分配内存。

2.当map被当作set集合来使用的时候可以把值设为空的结构体,因为set只需要使用键。而空结构体是不占内存的(相当于占位符),这样可以节省内存空间。

4.字符串的处理

当我们使用字符串追加的时候通常使用的是"+",因为string在go语言中是不可变类型,所以内存分配是固定的,所以每次+都会分配内存,带来的性能消耗也十分大。所以推荐使用string.Builder这个有内存扩容策略不需要每次都分配内存,其底层就是[]byte数组。其基本使用如下:

func PreStrBuild(n int, str string) string {
    //创建对象
   var builder strings.Builder
    //预分配内存
   builder.Grow(n * len(str))
   for i := 0; i < n; i++ {
    //进行拼接
      builder.WriteString(str)
   }
   return builder.String()
}

5.stomic包

因为锁是系统级别的调用,所以会产生用户态和内核态之间的来回切换,这样会消耗大量的cpu资源,其作用就是在并发编程中保护其中的一个变量,锁是保护一段逻辑,而原子操作是保护一个变量,其全是为了并发安全,但是atomic操作是通过硬件来实现,其效率比锁要高。

6.性能分析工具pprof

当我们已经完成好了业务代码的基本逻辑,我们也掌握了一些优化的手段,此时我们就需要对我们的程序进行优化,但是从哪下手于我们而言是一个比较需要关心的问题。我们不能凭感觉去修改一些代码,数据才是最真实的体现,所以我们就需要用到一个go语言自带的性能分析工具pprof。其是可视化分析性能和数据工具,我们可以通过这个工具获取关于性能的一系列信息。简介如下:

image.png

获取web端可视化命令:

命令行分析:

基本使用学习:

[wolfogre/go-pprof-practice: go pprof practice. (github.com)](https://github.com/wolfogre/go-pprof-practice)

总结

以上就是关于性能优化测试及其处理的内容,总而言之,首先必须实现项目,在讨论优化项目,优化中要懂得权衡利弊。