这是我参与「第五届青训营 」笔记创作活动的第3天
性能优化案例
- 预分配内存——slice()
- 尽可能在使用make()初始化切片时提供容量信息
- Map()也可以预分配内存来提升性能
func noPreAlloc(size int) {
data := make([]int, 0)
for i := 0; i < size; i++{
data = append(data, i)
}
}
func PreAlloc(size int) {
data := make([]int, 0, size)
for i := 0; i < size; i++{
data = append(data, i)
}
}
- 第二点:可以用copy替代re-slice,解决大内存不释放的问题
func getLastBySlice(origin []int) []int {
return origin[len(origin)-2:]
}
func getLastByCopy(origin []int) []int {
result := make([]int, 2)
result = origin[len(origin)-2:]
return result
}
- 字符串的三种处理方式
- 字符串在GO语言中是不可变类型,占用内存大小是固定的。
- ①使用 “+” 号来实现字符串拼接方式
// 使用 + 每次都会重新分配内存
func Plus(n int, str string) string {
s := ""
for i := 0; i < n; i++ {
s += str
}
return s
}
- 使用
strings.Builder
// Builder和Buffer底层都是Bytes[]数组,使用的是内存扩容策略
// Builder将底层的[]byte直接转换为字符串类型返回
func StrBuilder(n int, str string) string {
var builder strings.Builder
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
- 使用
bytes.Buffer
// Bufffer转换为字符串时从新申请一块空间
func ByteBuffer(n int, str string) string {
buf := new(bytes.Buffer)
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return buf.String()
}
- 空结构体不占内存,实现set时可以考虑使用map来替代
性能分析工具pprof
-
程序所耗费的CPU与MEMORY的可视化分析工具 项目案例地址:
(https://github.com/wolfogre/go-pprof-practice) -
使用命令查看CPU状态
go tool pprof "http://127.0.0.1:6060/debug/pprof/profile?seconds=10" -
可视化界面查看CPU性能
go tool pprof -http=:8080 "http://127.0.0.1:6060/debug/pprof/heap -
展示view
top:flat表示当前函数本身的执行耗时;cum表示当前函数本身加上其调用函数的总耗时。
,调用图:Graph,火焰图:FlameGraph,peek,源码:Source,反汇编:Disassemble
- 采样Sample
CPU,堆内存:Heap,协程goroutine,锁:mutex,阻塞:Block,线程创建:ThreadCreate。