性能优化指南 | 青训营

性能优化指南

这是我在字节跳动青训营学习的第34天,也是我参加《第六届青训营笔记伴读》的第七篇笔记

在优化性能之前,可以使用benchmark来查看性能表现 使用benchmark时,需要函数名由Benchmark开头,且参数为*testing.B,文件名后缀为_test

go 复制代码
go test -bench . -benchmem

性能优化建议

slice 预分配内存

  • 尽可能使用make()初始化切片时提供容量信息

  • slice本质是一个数组片段的描述

    • 包括数组指针
    • 片段的长度
    • 片段的容量(不改变内存分配情况下的最大长度)
  • 切片操作并不复制切片指向的元素

  • 创建一个新的切片会复用原来切片的底层数组

内存陷阱

在已有切片的基础上创建切片,不会创建新的底层数组,在这种情况下可以使用copy代替re-slice

map 预分配内存

  • 不断向map中添加元素的操作会触发map的扩容
  • 提前分配好的空间可以减少内存拷贝和Rehash的小号
  • 建议根据实际需求提前预估好需要的空间

使用Strings Builder

  • 常见的字符串拼接方式
go 复制代码
//直接拼接
func Plus(n int, str string) string {  
s := ""  
for i := 0; i < n; i++ {  
s += str  
}  
return s  
}
go 复制代码
//使用Builder
func StrBuilder(n int, str string) string {  
var builder strings.Builder  
for i := 0; i < n; i++ {  
builder.WriteString(str)  
}  
return builder.String()  
}
}
go 复制代码
// 使用buffer
func ByteBuffer(n int, str string) string {  
buf := new(bytes.Buffer)  
for i := 0; i < n; i++ {  
buf.WriteString(str)  
}  
return buf.String()  
}
}

可以看到Builder和buffer性能比string快了10倍

使用空结构体节省内存

  • 空结构体 Struct{}实例不占据任何内存空间
  • 对于Set,可以考虑用map来代替
    • 对于这个场景,只需要用到map的键,而不需要值
    • 即使是将map的值设置为bool类型,也会占据1个字节

使用atomic包

对于多线程场景,除了使用加锁的方式,还可以使用atomic包时间性能会好很多

  • 锁的视线是通过操作系统实现,属于系统调用
  • atomic操作是通过硬件实现,效率比锁高
  • sync.Mutex应该用来保护一段逻辑,不仅仅用于保护一个变量
  • 对于非数值操作,可以使用atomic.Value,能承载一个interface{}

小结

  • 避免常见的性能陷阱可以保证大部分程序的性能
  • 普通的应用代码,不要一味的追求程序的性能
  • 越高级的性能优化手段越容易出问题
  • 在满足正确可靠,简洁清晰的质量要求的前提下提高程序性能
相关推荐
CallBack8 个月前
Typora+PicGo+阿里云OSS搭建个人图床,纵享丝滑!
前端·青训营笔记
Taonce1 年前
站在Android开发者的角度认识MQTT - 源码篇
android·青训营笔记
AB_IN1 年前
打开抖音会发生什么 | 青训营
青训营笔记
monster1231 年前
结营感受(go) | 青训营
青训营笔记
翼同学1 年前
实践记录:使用Bcrypt进行密码安全性保护和验证 | 青训营
青训营笔记
hu1hu_1 年前
Git 的正确使用姿势与最佳实践(1) | 青训营
青训营笔记
星曈1 年前
详解前端框架中的设计模式 | 青训营
青训营笔记
tuxiaobei1 年前
文件上传漏洞 Upload-lab 实践(中)| 青训营
青训营笔记
yibao1 年前
高质量编程与性能调优实战 | 青训营
青训营笔记
小金先生SG1 年前
阿里云对象存储OSS使用| 青训营
青训营笔记