首頁 >後端開發 >Golang >將位元組檔案讀入 int64 切片的最有效方法是什麼?

將位元組檔案讀入 int64 切片的最有效方法是什麼?

PHPz
PHPz轉載
2024-02-09 11:36:09970瀏覽

将字节文件读入 int64 切片的最有效方法是什么?

php小編子墨在這裡為大家解答一個常見的問題:「將位元組檔案讀入int64 切片的最有效方法是什麼?」當我們需要將位元組文件讀入int64 切片時,可以採用以下方法:首先,使用file_get_contents 函數讀取位元組文件,然後使用unpack 函數將位元組文件解為int64 切片。這樣的方法簡單且高效,能夠快速地將位元組檔案轉換為 int64 切片,滿足我們的需求。希望這個方法能夠幫助大家!

問題內容

我有幾個打包的 int64 檔案。我需要它們在記憶體中作為 int64 切片。問題是檔案加在一起超過了機器記憶體大小的一半,因此空間有限。 go 中的標準選項類似:

a := make([]int64, f.Size()/8)
binary.Read(f, binary.LittleEndian, a)

不幸的是,binary 套件將立即分配一個大小為 f.size()*8[]byte,並耗盡記憶體。

如果我一次讀取每個位元組並將其複製到切片中,它確實可以工作,但這速度太慢了。

理想的情況是將[]byte 直接轉換為[]int64,只是告訴編譯器“好吧,這些現在是整數”,但顯然這是行不通的。有什麼方法可以完成類似的東西?可能使用不安全的包或在絕對需要時放入 c 中?

解決方法

我有幾個打包的 int64 檔案。我需要它們在記憶體中作為 int64 切片。問題是檔案加在一起超過了機器記憶體大小的一半,因此空間有限。

go 中的標準選項類似於:

a := make([]int64, f.Size()/8)
binary.Read(f, binary.LittleEndian, a)

不幸的是,二進位套件將立即分配一個大小為 f.size()*8 的 []byte,並耗盡記憶體。

所有函數都使用最少的記憶體。

// same endian architecture and data
// most efficient (no data conversion).
func readfileint64se(filename string) ([]int64, error) {
    b, err := os.readfile(filename)
    if err != nil {
        return nil, err
    }

    const i64size = int(unsafe.sizeof(int64(0)))
    i64ptr := (*int64)(unsafe.pointer(unsafe.slicedata(b)))
    i64len := len(b) / i64size
    i64 := unsafe.slice(i64ptr, i64len)

    return i64, nil
}

例如,為了amd64(littleendian)架構和littleendian資料最大效率(無需資料轉換),請使用readfileint64se

位元組順序謬誤 - rob pike
https://commandcenter.blogspot.com/2012/04/byte- order-fallacy.html

#
// littleendian in-place data conversion for any architecture
func readfileint64le(filename string) ([]int64, error) {
    b, err := os.readfile(filename)
    if err != nil {
        return nil, err
    }

    const i64size = int(unsafe.sizeof(int64(0)))
    i64ptr := (*int64)(unsafe.pointer(unsafe.slicedata(b)))
    i64len := len(b) / i64size
    i64 := unsafe.slice(i64ptr, i64len)

    for i, j := i64size, 0; i <= len(b); i, j = i+i64size, j+1 {
        i64[j] = int64(binary.littleendian.uint64(b[i-i64size : i]))
    }

    return i64, nil
}
// BigEndian in-place data conversion for any architecture
func readFileInt64BE(filename string) ([]int64, error) {
    b, err := os.ReadFile(filename)
    if err != nil {
        return nil, err
    }

    const i64Size = int(unsafe.Sizeof(int64(0)))
    i64Ptr := (*int64)(unsafe.Pointer(unsafe.SliceData(b)))
    i64Len := len(b) / i64Size
    i64 := unsafe.Slice(i64Ptr, i64Len)

    for i, j := i64Size, 0; i <= len(b); i, j = i+i64Size, j+1 {
        i64[j] = int64(binary.BigEndian.Uint64(b[i-i64Size : i]))
    }

    return i64, nil
}

以上是將位元組檔案讀入 int64 切片的最有效方法是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除