性能优化指南:

126 阅读1分钟

性能优化指南:

如何查看我们写出来的程序的性能?-Benchamrk

如何使用?

Go语言提供了支持基准性能测试的benchmark的工具:

调用命令:

go test -bench=. -benchmem

我自己在goland里面写实现了一下:

项目视图

源码:

//fab.go
package fib
​
func fabnacci(i int) int {
    if i == 0 {
        return 0
    } else if i == 1 {
        return 1
    } else {
        return fabnacci(i-1) + fabnacci(i-2)
    }
}
​
//fab_test.go
package fib
​
import "testing"func BenchmarkFib10(b *testing.B) {
    for i := 0; i < b.N; i++ {
        fabnacci(10)
    }
}
​

结果:

image-20230605200845654

接下来利用benchmark查看性能来对开发进行优化:

1.在slice切片中:

1.初始化时指定size

通过跑实际例子来看性能发现:对于占用内存大概可以估算的工程,最好在建立slice时就指定长度。这样会大大减少申请内存的次数从而大幅度节省时间。

2.在对元素进行拷贝

在引用切片时如果使用的是切片构成的数组的很小的一部分的画,建议将所需的部分拷贝出来然后再使用。

因为切片类似于视图,哪怕你再调用一个切片时用的是很少的一部分,他只是给你把那部分呈现出来而已,再底层上还是对一片大的没用释放的内存进行处理。所以在局部使用切片的某一部分时更好的方式是拷贝而不是直接调用。

在map中:

与在slice中相同,在初始化时最好给出size

string拼接:

1.3.4 性能优化建议-字符串处理

使用 strings.Builder 使用 + 拼接性能最差,strings.Builder, bytes.Buffer 相近,strings.Buffer 更快 分析 字符串在 Go 语言中是不可变类型,占用内存大小是固定的 使用 + 每次都会重新分配内存 strings.Builder,bytes.Buffer 底层都是 Dbyte 数组 内存扩容策略,不需要每次拼接重新分配内存

再结合我们前面所说的长度预分配问题:

我们可以利用Grow函数来为内存空间(builder/buffer)预先指定空间的大小从而提升性能。

image-20230605203852034

空结构体:

在进行线程互斥的时候用atomic包来提升性能

image-20230605204353644

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