性能优化指南 | 青训营

性能优化指南

这是我在字节跳动青训营学习的第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{}

小结

  • 避免常见的性能陷阱可以保证大部分程序的性能
  • 普通的应用代码,不要一味的追求程序的性能
  • 越高级的性能优化手段越容易出问题
  • 在满足正确可靠,简洁清晰的质量要求的前提下提高程序性能
相关推荐
静水流深39714 小时前
03 模型IO| 豆包MarsCode AI刷题
青训营笔记
用户247841860022 天前
第七次算法笔记 | 豆包MarsCode AI刷题
青训营笔记
幻66 天前
小S的倒排索引 | 豆包MarsCode AI刷题
青训营笔记
用户826014428307 天前
469. 环形数组最大子数组和问题
青训营笔记
用户605721920988 天前
奇妙货币交易问题 | 豆包MarsCode AI刷题
青训营笔记
我明天再来学Web渗透9 天前
“抖音互联网架构分析及高可用系统构建思考”(方向三)| 豆包MarsCode AI刷题
青训营笔记
用户3021330662010 天前
第三次刷题 | 豆包MarsCode AI刷题
青训营笔记
用户91059730277015 天前
CSS详解| 豆包MarsCode AI刷题
青训营笔记
huyck15 天前
伴学笔记1|豆包MarsCode AI 刷题
青训营笔记
用户197009008153820 天前
实现一个TodoList | 青训营 x 豆包MarsCode技术训练营
青训营笔记