首頁 > 後端開發 > Golang > 主體

為什麼將'interface{}”轉換回切片會導致額外的堆分配?

PHPz
發布: 2024-02-12 22:15:09
轉載
780 人瀏覽過

為什麼將interface{}”轉換回切片會導致額外的堆分配?

在PHP中,將「interface{}」類型轉換為切片(slice)類型時,會導致額外的堆分配。這是因為在PHP中,介面(interface)是一種抽象的資料類型,而切片是一種動態數組類型。當我們將介面類型轉換為切片類型時,PHP需要為切片類型分配額外的記憶體空間來儲存切片的元素。這個額外的堆分配操作會導致記憶體的額外開銷,對於一些記憶體敏感的應用程式來說,可能會帶來效能問題。因此,在進行類型轉換時,我們應該注意這個問題,並盡量避免不必要的額外堆分配。

問題內容

func benchmarkpool(b *testing.b) {
    b.reportallocs()
    p := sync.pool{new: func() interface{} {
        return make([]byte, 1024)
    }}
    for i := 0; i < b.n; i++ {
        bts := p.get().([]byte)
        p.put(bts)
    }
}
登入後複製

此基準測試在 go1.19.5 中給出以下輸出。

benchmarkpool
benchmarkpool-10        47578498            24.47 ns/op       24 b/op          1 allocs/op
登入後複製

當使用 *[]byte 時,事情會變得不同:

func benchmarkpool(b *testing.b) {
    b.reportallocs()
    p := sync.pool{new: func() interface{} {
        bts := make([]byte, 1024)
        return &bts
    }}
    for i := 0; i < b.n; i++ {
        bts := p.get().(*[]byte)
        p.put(bts)
    }
}
登入後複製
BenchmarkPool
BenchmarkPool-10        142008002            8.581 ns/op           0 B/op          0 allocs/op
登入後複製

似乎將 interface{} 轉換回切片會導致額外的堆疊分配。

為什麼 go 需要這個額外的分配?背後的設計考量是什麼?

解決方法

造成分配的不是any[]byte 的轉換,而是[]byteany 的轉換。 p.Put(bts) 將參數bts 隱含轉換為any,然後再傳遞給(*sync.Pool).Put 。 GoGC 1.19 中的介面被實作為一對指針,一個指向類型元數據,一個指向實際對象,在這種情況下,第二個指針轉義到池,導致分配切片對象。這不僅適用於切片類型,也適用於任何其他非指標類型。

對於指針,例如*[]byte,編譯器會執行最佳化,將其值直接放入iface 結構中,從而在轉換為介面時刪除 *[]byte 實例的指派。因此,通常建議將指標放入池中而不是結構本身。

以上是為什麼將'interface{}”轉換回切片會導致額外的堆分配?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板