你為什麼要喜歡 sync.Pool?

2019-10-27     Go語言中文網

介紹

因為它很快。通過文章底部存儲庫中的基準測試可以減少 4982 倍的內存占用。

Comparing pool performance. Less than better.

相比之下, Pool 的性能更快更好。

Ok, 這究竟是怎麼回事呢?

垃圾回收定期執行。如果你的代碼不斷地在一些數據結構中分配內存然後釋放它們,這就會導致收集器的不斷工作,使得更多的內存和 CPU 被用來在初始化結構體時分配資源。

對sync/pool.go[1] 的描述如下:

Pool 是一組可以單獨保存和檢索的臨時對象。

Pool 可以安全地同時使用多個 Goroutine。

sync.Pool允許我們重用內存而非重新分配。

此外,如果你使用的 http 伺服器接收帶有 JSON 請求體的 post 請求,並且它必須被解碼到結構體中,你可以使用 sync.Pool 來節省內存並減少伺服器響應時間。

sync.Pool 用法

sync.Pool 構造很簡單:

var bufferPool = sync.Pool{
\tNew: func() interface{} {
\t\treturn new(bytes.Buffer)
\t},
}

現在你將會創建一個 Pool 和新的緩衝區。你可以這樣創建第一個緩衝區:

buffer := bufferPool.Get().(*bytes.Buffer)

get 方法會返回 Pool 中已存在的 *bytes.Buffer,否則將調用 New 方法來初始化新的 *bytes.Buffer

但在緩衝區使用後,你必須將其重置並放回 Pool 中:

buffer.Reset()
bufferPool.Put(buffer)

基準測試

將 JSON 編碼為 bytes.Buffer

// 對 JSON 編碼的代碼段
BenchmarkReadStreamWithPool-8 5000000 384 ns/op 0 B/op 0 allocs/op
BenchmarkReadStreamWithoutPool-8 3000000 554 ns/op 160 B/op 2 allocs/op

我們得到了 44% 的性能提升並且節省了非常多的內存 (160B/ops vs 0B/ops)。

將位元組寫入 bufio.Writer

BenchmarkWriteBufioWithPool-8 10000000 123 ns/op 128 B/op 2 allocs/op
BenchmarkWriteBufioWithoutPool-8 2000000 651 ns/op 4288 B/op 4 allocs/op

我們得到了 5 倍性能提升並且減少了 32 倍內存使用。

將 JSON 解碼為 struct

BenchmarkJsonDecodeWithPool-8 1000000 1729 ns/op 1128 B/op 8 allocs/op
BenchmarkJsonDecodeWithoutPool-8 1000000 1751 ns/op 1160 B/op 9 allocs/op

因為 JSON 解碼操作太難,我們的性能只提升了 1%,我們無法通過重用結構體得到正常的提升。

Gzip 位元組

BenchmarkWriteGzipWithPool-8 500000 2339 ns/op 162 B/op 2 allocs/op
BenchmarkWriteGzipWithoutPool-8 10000 105288 ns/op 807088 B/op 16 allocs/op

等等,什麼?性能提升了 45 倍並且內存使用量減少了 4982 倍。

總結

務必使用 sync.Pool !它確實可以節省內存並提高應用程式的性能。

基準測試的 Github 存儲庫在這裡[2]


via: https://medium.com/@Mnwa/why-you-should-like-sync-pool-2c7960c023ba

作者:Mnwa Mnowich[3]譯者:RookieWilson[4]校對:polaris1119[5]

本文由 GCTT[6] 原創編譯,Go 中文網[7] 榮譽推出


喜歡本文的朋友,歡迎關注「Go語言中文網」:

文中連結

[1]sync/pool.go: https://golang.org/src/sync/pool.go

[2]這裡: https://github.com/Mnwa/GoBench

[3]Mnwa Mnowich: https://medium.com/@Mnwa

[4]RookieWilson: https://github.com/RookieWilson

[5]polaris1119: https://github.com/polaris1119

[6]GCTT: https://github.com/studygolang/GCTT

[7]Go 中文網: https://studygolang.com/

文章來源: https://twgreatdaily.com/JgqvD24BMH2_cNUgxDHo.html