性能优化|青训营笔记

137 阅读2分钟

性能优化|青训营笔记

这是我参与[第五届青训营]伴学笔记创作活动的第3天,今天学习的是性能优化部分

简介

  • 性能优化是综合评估,有时候时间效率和空间效率可能冲突
  • 性能优化的前提是满足正确可靠、简洁清晰等质量因素

性能测试工具-Benchmark(go语言自带)

写一个benchmark测试

  1. 基准测试代码文件必须是_test.go结尾,和单元测试一样;
  2. 基准测试的函数以Benchmark开头;
  3. 参数须为 *testing.B;
  4. 基准测试函数不能有返回值;
  5. b.ResetTimer是重置计时器,这样可以避免for循环之前的初始化代码的干扰;
  6. b.N是基准测试框架提供的,Go会根据系统情况生成,不用用户设定,表示循环的次数,因为需要反复调用测试的代码,才可以评估性能;

性能优化笔记.md155410.6255682.png 执行测试的五个结果依次为:1.cpu核数 2.测试次数 3.每次消耗时间 4.每次消耗内存 5.每次执行申请了几次内存

性能优化笔记.md149523.4780754.png

性能优化建议

Slice

  • 使用时尽量预分配内存

    因为如果不先申请内存,当切片容量不够时,会自动扩容申请内存,会比较耗费时间。所以尽量在创建切片时就预置容量。

  • 在已有切片的基础上创建切片,尽量用copy代替直接创建切片。

因为代码在原切片上新建切片,原切片不需要的那段内存得不到释放,比较消耗资源

map

  • 预分配内存,和slice一样 (不断向map中添加元素的操作会触发map的扩容,提前分配好空间可以减少内存拷贝和Rehash的消耗)

    map和slice都需要提前预估好需要的空间

字符串处理

用string.Builder处理速度最快

  • 使用‘+’号进行字符串拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Buffer更快

分析

字符串在Go语言中是不可变类型,占用内存大小是固定的,使用+每次都会重新分配内存 strings.Builder,bytes.Buffer底层都是[]byte数组内存扩容策略,不需要每次拼接重新分配内存。

结构体

  • 空结构体struct{}的实例不占内存空间。其中不含有任何数据,那有什么意义呢?我们常把它作为占位符使用

线程安全

用atomic包的时间性能比加锁更好

  • 锁的实现是通过操作系统来实现,属于系统调用,占用资源多。
  • atomic操作是通过硬件实现,效率比锁高