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

什麼逃逸到堆中?

王林
發布: 2024-02-06 10:09:07
轉載
1214 人瀏覽過

什麼逃逸到堆中?

問題內容

我有這段程式碼,本來應該根本不進行分配,但由於某種原因它確實進行了分配。正如基準測試所說,每個操作發生 2 次分配。

函數的哪幾行進行分配?為什麼?

功能:

func (vi *VarInt /* int32 */) Read(input io.Reader) error {
    var (
        b     byte
        buf   = unsafe.Slice(&b, 1)
        shift int
        value uint32
    )
    for {
        _, err := io.ReadFull(input, buf)
        if err != nil {
            return err
        }

        value |= (uint32(b) & 0b01111111) << shift

        if (b & 0b10000000) == 0 {
            *vi = VarInt(value)
            return nil
        }

        shift += 7
        if shift >= 32 {
            return ErrVarIntTooLong
        }
    }
}

func (vi *VarInt /* int32 */) Write(output io.Writer) error {
    var (
        varint [5]byte
        uvalue = uint32(*vi)
        x      int
    )
    for ; ; x++ {
        vb := uint8(uvalue)

        if (vb & 0b10000000) == 0 {
            varint[x] = vb
            break
        }

        varint[x] = (vb & 0b01111111) | 0b10000000

        uvalue >>= 7
    }

    _, err := output.Write(varint[:x+1])
    if err != nil {
        return err
    }

    return nil
}
登入後複製

基準:

func BenchmarkVarInt(b *testing.B) {
    var buf bytes.Buffer
    buf.Grow(5)
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        vi := (VarInt)(i)
        vi.Write(&buf)
        vi.Read(&buf)
        buf.Reset()
    }
}
登入後複製

我想buf 切片以某種方式逃逸,但我不知道如何逃逸,因為據我了解,在這種情況下切片是在堆疊上分配的結構,它將指向變數b 作為其數據。我嘗試將表達式unsafe.Slice(&b, 1) 更改為(*[1]byte)(unsafe.Pointer(&b))[:],但它沒有任何改變。


正確答案


當一個值被裝箱在介面中時,它總是被認為是逃逸的-即使該值從未在呼叫堆疊之外使用過,Go 也會在此時停止分析並認為有人可能已經掌握了該地址,因此該值必須存放在堆上。

由於Read 採用io.ReaderWrite 採用io.Writer,因此buf (這是傳遞給這兩個函數的bytes.Buffer )必須轉義。

即使您讓這些函數採用具體類型bytes.Buffer (您可能不想要),但這還不夠,因為Read 呼叫io.ReadFull ,它又採用io.Reader 。您必須比這更加努力才能使此分配免於分配。

作為旁注,對於Read 中的其他問題,有一個更簡單的解決方案,不需要任何unsafe.Slice 惡作劇:只需將var b byte 替換為var b [1]byte (這正是記憶體中相同),將b[:]傳遞給ReadFull ,並在其他使用b的地方使用b[0]

以上是什麼逃逸到堆中?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!