这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天,今天主要对昨天课程内容中的性能调优部分进行总结
性能优化
Go语言的性能优化前提需要满足正确可靠、简洁清晰等目标;此外,性能优化需要综合评估,因此有时时间效率和空间效率可能对立;
Benchmark 测试
在优化一段函数或者一个包的代码前后,我们可以使用Go内置的Benchmark进行测试。具体用法可参考这里:geektutu.com/post/hpg-be…
Slice优化
Slice的本质是一个数组片段的描述,包括了数组片段的指针、长度和最大容量,而切片的操作并不会复制切片指向的元素。基于这一点,我们应该提前为切片分配一定的内存,以免频繁地扩容而导致触发频繁地访存操作。 此外,创建一个新的切片也会复用原切片指向的底层数组。基于这一点,我们在大切片的基础上进行复制时,应该使用copy代替直接的切片赋值,以免大切片的底层数组一直被占用而不得释放,从而损耗内存。
Map优化
与Slice类似,不断往map中添加新元素也会触发扩容、内存拷贝、rehash等操作,因此可以根据实际需求提前预估分配确定的空间。
字符串优化
字符串拼接是程序中较为常用的功能,常见的方法有使用“+”运算符,使用strings.Builder、使用bytes.Buffer这三种方法。经过分析与测试,strings.Builder的实现是最快的。
空结构体的妙用
空结构体struct{}实例不占据内存空间,可作为各种场景下的占位符使用,从而达到节省资源的目的。下面是一种常见的Set实现。
atomic包
为了保证程序的并发安全,我们常用锁或者atomic(原子操作)来保证并发正确性。锁的功能属于系统调用,由操作系统来实现,而atomic操作则通过硬件实现,效率比锁更高。
性能分析工具 pprof
对于系统的整体性能,需要有专门的工具帮助我们系统而全面地分析。Go语言自带了一个性能分析工具pprof,它的功能十分强大。
具体的功能这里不赘述,大家可以通过下面的指南和实践项目进行学习: