这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
高质量编程与性能调优学习总结
性能优化建议
关于Slice
Slice预分配内存
-
我们在编写代码的过程中,最好尽可能的使用make()初始化切片的时候提供切片的容量信息
-
切片的本质是一个数组片段的描述
- 包括数组指针
- 片段的长度
- 片段的容量(在不改变内存分配情况下的最大长度)
-
切片操作并不复制切片指向的元素
-
当我们创建一个新的切片时会复用原来切片的底层数组
type slice struct {
array unsafe.Pointer
len int
cap int
}
- slice的另外一个缺陷:存在大内存未释放的情况
- 在已有切片的基础上创建切片,不会创建新的底层数组,我们可以使用copy来代替re-slice
关于Map
Map预分配内存
- 不断地向map中添加元素的操作会触发map的扩容
- 提前分配好空间可以减少内存的拷贝和 Rehash 的消耗
- 我们可以根据项目的实际需求来提前预估和准备需要的空间
关于字符串处理
在go语言开发学习中,存在如下几个常见的字符串拼接方法
第一种
func Plus(n int, str string) string {
s := ""
for i:=0; i<n; i++ {
s += str
}
return s
}
第二种
func StrBuilder(n int, str string) string {
var builder strings.Builder
for i:=0; i<n; i++ {
builder.WriteString(str)
}
return builder.String()
}
第三种
func ByteBuffer(n int, str string) string {
buf := new(bytes.Buffer)
for i:=0; i<n; i++ {
buf.WriteString(str)
}
return buf.String()
}
性能评估结果:使用 + 拼接性能最差,strings.Builder,bytes.Buffer相近,strings.Builder更快
原因:
- 字符串在go语言中是不可变类型,占用内存大小是固定的
- 使用 + 每次都会重新分配内存
- strings.Builder,bytes.Buffer 底层都是 []byte 数组
- 内存扩容策略,不需要每次拼接重新分配内存