假如要获取一组一定长度的整形数组,是使用固定长度初始化数组的性能高还是使用 make() 然后不断追加 (append) 产生数组的性能高呢?
如果你选了其中一个,都不对。为什么?看数据吧
在这里分别设置获取不同数量级 lenFix 长度的数组为例:
const lenFix = 10 000 //fix is better than make
~/golang/src/demo/10things/pack ᐅ go test -bench=. -benchmem -blockprofile p.out -coverprofile cover.out -memprofile mem.out
testing: warning: no tests to run
PASS
BenchmarkGroupedGlobalsMake 30000 57851 ns/op 81920 B/op 1 allocs/op
BenchmarkGroupedGlobalsFix 100000 24426 ns/op 0 B/op 0 allocs/op
coverage: 27.6% of statements
ok demo/10things/pack 5.113s
const lenFix = 100 000 //equal
~/golang/src/demo/10things/pack ᐅ go test -bench=. -benchmem -blockprofile p.out -coverprofile cover.out -memprofile mem.out
testing: warning: no tests to run
PASS
BenchmarkGroupedGlobalsMake 5000 261474 ns/op 802816 B/op 1 allocs/op
BenchmarkGroupedGlobalsFix 5000 278088 ns/op 0 B/op 0 allocs/op
coverage: 27.6% of statements
ok demo/10things/pack 2.863s
const lenFix = 1000 000 //fix is slow than make nearly haf
~/golang/src/demo/10things/pack ᐅ go test -bench=. -benchmem -blockprofile p.out -coverprofile cover.out -memprofile mem.out
testing: warning: no tests to run
PASS
BenchmarkGroupedGlobalsMake 500 3113893 ns/op 8003584 B/op 1 allocs/op
BenchmarkGroupedGlobalsFix 300 4785933 ns/op 0 B/op 0 allocs/op
coverage: 27.6% of statements
ok demo/10things/pack 3.927s
const lenFix = 10 000 000 //make is better than fix
~/golang/src/demo/10things/pack ᐅ go test -bench=. -benchmem -blockprofile p.out -coverprofile cover.out -memprofile mem.out
testing: warning: no tests to run
PASS
BenchmarkGroupedGlobalsMake 50 28069067 ns/op 80003072 B/op 1 allocs/op
BenchmarkGroupedGlobalsFix 20 66387139 ns/op 80003072 B/op 1 allocs/op
coverage: 27.6% of statements
ok demo/10things/pack 4.682s
const lenFix = 100 000 000 //fix occurs error but make runs normally
~/golang/src/demo/10things/pack ᐅ go test -bench=. -benchmem -blockprofile p.out -coverprofile cover.out -memprofile mem.out
testing: warning: no tests to run
PASS
BenchmarkGroupedGlobalsMake 2 681053704 ns/op 800006144 B/op 1 allocs/op
BenchmarkGroupedGlobalsFix runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
可以看在大概100 000个长度之前,使用固定长度类型的数组所需要的时间是比使用 make 方法获取的数组的时间要短,但一超过这个长度后则相反。固定长度类型的数组初始化不需要进行内存的申请操作,减缓 GC 的触发频率,而 make 则必须要进行一次内存的 alloc 操作, 但是 make 在实际应用中会么比较灵活一点,毕竟可以方便的进行数组增长(其实背后也是复制原来的数据到新申请的数组中), 还有,固定数组的初始化有长度限制,超过 stack 所允许的容量时就会现fatal error: stack overflow错误,所以在实际开发中还是使用 make 更为安全可靠。
—update—
原来 make() 是在 heap 中创建,而直接用 [count]int 使用的是 stack 的空间,golang.1.4.x 所允许的最大 stack 为 2MB(1<<20), 该值对应于 runtime/stack.c 中的 runtime·maxstacksize