Pointer Performance
我在O`REILLY出的一本書 "Go學習手冊"內有看到一個很有趣的段落: 指標傳遞性能 ( Pointer Performance )
我把這段的重點直接整理下來(因為很重要) 如下:
- 無論資料的大小為何,將指標傳入函式的時間都是固定的,大約是1 nanosecond。
- 如果struct夠大,將struct的指標當成輸入參數或是回傳值可以改善性能。
- 回傳指標 vs. 回傳值的行為比較有意思。如果資料結構小於1MB,回傳指標型別其實比回傳值更慢。例如: 100-byte的資料結構大約要花10 nanosecond 來回傳,但是那個資料結構的指標大約要花30 nanosecond。當資料結構超過1MB,性能優勢就會逆轉,回傳10MB的資料大約要花2 millisecond,但是回傳它的指標大約是0.5millisecond再多一些。
Why? 因為指標的背後有很複雜的資料流 ( 實例化struct 會存放在 Heap Memory 並且 Golang 會為記憶體回收行程創造額外的工作。
這本書的作者有提供 Benchmark Test 測試程式:
https://github.com/learning-go-book/pointer_performance
下列結果是在我的Windows10上用VirtualBox起一個Ubuntu 21.04的虛擬機 ( 1 core + 2048MB )所執行測試後的結果:
danny@ubuntu21-danny:~/git/pointer_performance$ go test -v -bench=. -run=none .
goos: linux
goarch: amd64
pkg: pointer_value_param_perf
cpu: AMD Ryzen 7 5800U with Radeon Graphics
BenchmarkPointer10In
BenchmarkPointer10In 1000000000 1.185 ns/op
BenchmarkValue10In
BenchmarkValue10In 759692007 1.575 ns/op
BenchmarkPointer10Out
BenchmarkPointer10Out 84897354 13.06 ns/op
BenchmarkValue10Out
BenchmarkValue10Out 195042046 6.175 ns/op
BenchmarkPointer100In
BenchmarkPointer100In 874474899 1.375 ns/op
BenchmarkValue100In
BenchmarkValue100In 399738804 3.009 ns/op
BenchmarkPointer100Out
BenchmarkPointer100Out 57985454 18.68 ns/op
BenchmarkValue100Out
BenchmarkValue100Out 141442026 8.496 ns/op
BenchmarkPointer1_000In
BenchmarkPointer1_000In 871008984 1.377 ns/op
BenchmarkValue1_000In
BenchmarkValue1_000In 84154417 14.29 ns/op
BenchmarkPointer1_000Out
BenchmarkPointer1_000Out 19870842 58.50 ns/op
BenchmarkValue1_000Out
BenchmarkValue1_000Out 28082719 42.77 ns/op
BenchmarkPointer100_000In
BenchmarkPointer100_000In 867662985 1.398 ns/op
BenchmarkValue100_000In
BenchmarkValue100_000In 733471 1660 ns/op
BenchmarkPointer100_000Out
BenchmarkPointer100_000Out 346294 3788 ns/op
BenchmarkValue100_000Out
BenchmarkValue100_000Out 348529 3371 ns/op
BenchmarkPointer1_000_000In
BenchmarkPointer1_000_000In 864200361 1.395 ns/op
BenchmarkValue1_000_000In
BenchmarkValue1_000_000In 56034 24777 ns/op
BenchmarkPointer1_000_000Out
BenchmarkPointer1_000_000Out 45961 28100 ns/op
BenchmarkValue1_000_000Out
BenchmarkValue1_000_000Out 20671 59030 ns/op
BenchmarkPointer10_000_000In
BenchmarkPointer10_000_000In 852951956 1.390 ns/op
BenchmarkValue10_000_000In
BenchmarkValue10_000_000In 1615 732429 ns/op
BenchmarkPointer10_000_000Out
BenchmarkPointer10_000_000Out 4448 229350 ns/op
BenchmarkValue10_000_000Out
BenchmarkValue10_000_000Out 780 1538157 ns/op
PASS
ok pointer_value_param_perf 32.999s
P.S:
Benchmark 測試是透過 go test 指令加上 -bench=.,這樣才會跑 benchmark 部分,否則預設只有跑測試程式。另外 -run 可以用在跑特定的測試函式,但是假設沒有指定 -run 時,會預設跑測試 + Benchmark。這邊補上 -run=none 的用意是不要跑任何測試,只跑 Benchmark
No comments:
Post a Comment