為什麼將'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
的轉換,而是[]byte
到any
的轉換。 p.Put(bts)
將參數bts
隱含轉換為any
,然後再傳遞給(*sync.Pool).Put
。 GoGC 1.19 中的介面被實作為一對指針,一個指向類型元數據,一個指向實際對象,在這種情況下,第二個指針轉義到池,導致分配切片對象。這不僅適用於切片類型,也適用於任何其他非指標類型。
對於指針,例如*[]byte
,編譯器會執行最佳化,將其值直接放入iface
結構中,從而在轉換為介面時刪除 *[]byte
實例的指派。因此,通常建議將指標放入池中而不是結構本身。
以上是為什麼將'interface{}”轉換回切片會導致額外的堆分配?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

short 是 Java 中表示 16 位元有符號整數的原始資料類型,其範圍為 -32,768 到 32,767。它常用於表示小整數,如計數器或 ID,並支援基本算術運算和類型轉換。但由於 short 是一種有符號類型,使用除法時需謹慎,以避免溢位或下溢。

IFNULL 函數用於檢查表達式是否為 NULL,如果是則傳回指定的預設值,否則傳回表達式的值。它可以防止空值導致錯誤,允許操作空值,提高查詢的可讀性。用法包括:將空值替換為預設值、排除空值進行計算和巢狀使用處理多個空值情況。

Java 中的char 類型用於儲存單一Unicode 字符,佔2 個字節,範圍從U+0000 到U+FFFF,主要用於儲存文字字符,可以透過單引號或Unicode 轉義序列初始化,可參與比較、相等性、不相等性和連接運算,可隱式轉換為int 類型,也可以明確轉換為Character 物件。

C 語言中,除法運算子 / 的行為取決於運算元的資料型態:整數除法:當操作數為整數時,進行整數除法,結果向下取整。浮點數除法:操作數為浮點數時,進行浮點數除法,結果為浮點數。類型轉換:一個操作數為整數,另一個不是時,整數會隱式轉換為浮點數,然後進行浮點數除法。除數為 0:除數為 0 時產生數學誤差。取模運算:使用 % 運算子進行取模運算,而非除法取模。

MySQL 中的星號 (*) 表示“所有”,具有不同用法:選擇所有列選擇所有行JOIN 表LIKE 子句的通配符REGEXP 子句的量詞隱式類型轉換

C++函數重載匹配規則如下:匹配呼叫中參數數量和類型。參數順序必須一致。 constness和引用的修飾符必須匹配。可使用預設參數。

Oracle 中加號(+)運算子可用於:連接字串、數字、日期和時間間隔;處理 NULL 值,將 NULL 轉換為非 NULL 值;轉換資料類型為字串類型。

讓我們一起探討隱式類型轉換的常見應用場景!導言:在程式語言中,隱式型別轉換是一種自動執行的資料型別轉換過程。在一些程式語言中,這種轉換是隱含進行的,無需明確地告訴編譯器或解釋器進行轉換。隱式類型轉換在程式設計中擁有廣泛的應用場景,本文將針對其中一些常見的應用場景進行討論。數值計算中的隱式類型轉換在數值計算中,經常需要進行不同類型的資料之間的運算。當不同類型的數據
