很多时候我们需要对数据进行复制,在申请新的内存空间之后,我们可以用copy、append、for来复制拷贝。性能如何呢?

拷贝测试

 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
57
58
59
60
var target []byte
var source string

func init() {
	target = make([]byte, 256, 256)
	source = "asdfas+dfjad;sfja;dsfja;sdfjad;sjf;asdjf adsjfadsjfaksj"
}

func CopyArray() {
	copy(target, source)
}

func AppendArray() {
	target = target[0:0]
	target = append(target, source...)
}

func LoopAppendArray() {
	tmp := target[0:0]
	for i := range source {
		tmp = append(tmp, source[i])
	}
	target = tmp
}

func LoopArray() {
	for i := range source {
		target[i] = source[i]
	}
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// TEST
func BenchmarkCopyArray(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		CopyArray()
	}
}

func BenchmarkAppendArray(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		AppendArray()
	}
}

func BenchmarkLoopAppendArray(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		LoopAppendArray()
	}
}

func BenchmarkLoopArray(b *testing.B) {
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		LoopArray()
	}
}

测试结果如下:

cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkCopyArray-16           453242040                2.650 ns/op           0 B/op          0 allocs/op
BenchmarkAppendArray-16         340650312                3.513 ns/op           0 B/op          0 allocs/op
BenchmarkLoopAppendArray-16     24512456                48.90 ns/op            0 B/op          0 allocs/op
BenchmarkLoopArray-16           22199775                54.54 ns/op            0 B/op          0 allocs/op

如果将上面Append相关示例修改一下:

1
2
3
4
5
6
func LoopAppendArray() {
	target = target[0:0]
	for i := range source {
		target = append(target, source[i])
	}
}

上面不用局部变量代理slice,测试结果如下:

cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkCopyArray-16           454175919                2.642 ns/op           0 B/op          0 allocs/op
BenchmarkAppendArray-16         339231340                3.505 ns/op           0 B/op          0 allocs/op
BenchmarkLoopAppendArray-16     18401294                65.28 ns/op            0 B/op          0 allocs/op
BenchmarkLoopArray-16           22653690                52.94 ns/op            0 B/op          0 allocs/op

为什么会出现性能下降的问题呢?因为局部一般用寄存器存储计算,速度快于堆栈内存存取速度。

结论:

  1. Copy的性能比Append略好。
  2. 能一次Copy批量复制值,绝对不要循环单个复制。
  3. 循环处理数据,特别涉及修改值而且循环次数过多时,要想办法用局部变量做代理。

(完)