有几个 tips 对提高 go 性能有帮助,分享一下
Reflection 是昂贵的
用 Reflection
来获取变量类型很方便,但会有性能消耗
代码行数的增加并不一定减少性能
比如下面功能的函数:
1
2
3
func add(items []string, item string) []string{
return append(items,item)
}
代码很简洁、易懂,但性能不好,较好的方式:
1
2
3
4
5
6
7
8
9
func add(items []string, item string) []string{
n := len(items)
output := make([]string, n+1)
for index, val := range items {
output[index] = val
}
output[n] = item
return output
}
基准测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package loc
import (
"os"
"testing"
)
const maxElements = 1000
var elements = make([]int, maxElements)
func TestMain(m *testing.M) {
for i := 0; i < maxElements; i++ {
elements[i] = i
}
os.Exit(m.Run())
}
func Add(items []int, item int) []int {
return append(items, item)
}
func Add2(items []int, item int) []int {
n := len(items)
output := make([]int, n+1)
output[n] = item
copy(items[0:n], output)
return output
}
func BenchmarkAdd(b *testing.B) {
b.ReportAllocs()
var result []int
for i := 0; i < b.N; i++ {
b.StartTimer()
result = Add(elements, 10)
}
if len(result) != maxElements+1 {
b.Fatalf("Invalid number of elements, expected %d but retrieved %d", maxElements+1, len(result))
}
}
func BenchmarkAdd2(b *testing.B) {
b.ReportAllocs()
var result []int
for i := 0; i < b.N; i++ {
b.StartTimer()
result = Add2(elements, 10)
}
if len(result) != maxElements+1 {
b.Fatalf("Invalid number of elements, expected %d but retrieved %d", maxElements+1, len(result))
}
}
// go test -bench=. -benchmem -memprofile memprofile.out -cpuprofile profile.out
当往 1000 个元素的数组添加一个元素时,第二种的性能是第一种的两倍。
使用内联函数
Testing
对象、变量尽可能长时间保留在内存中
Benchmark tests (基准测试)
本文网址: https://golangnote.com/topic/248.html 转摘请注明来源
There are 3 Comments to "提高go运行性能小技巧"
个人认为这种情况预先加cap会比较靠谱。
@smallwhite #1 预分配好,前提是预知长度。
copy(items[0:n], output)
是不是应该换成copy(output[:n], items)
?这样返回的
output
只有一个值吧