Go中最快的数据加载方式

时间:2018-08-22 18:53:56

标签: go

我需要定期将超过300'000 rows x 78 columns的数据加载到Go程序中。

当前我使用(import github.com/360EntSecGroup-Skylar/excelize):

xlsx, err := excelize.OpenFile("/media/test snaps.xlsm")
if err != nil {
    fmt.Println(err)
    return
}

//read all rows into df
df := xlsx.GetRows("data")

在使用Samsung 960 EVO系列-M.2内置SSD的体面的PC上,大约需要 4 分钟。

是否有更快的方式加载此数据?目前,读取数据比处理数据需要更多时间。我还打开了其他文件格式。

1 个答案:

答案 0 :(得分:3)

如注释中所建议,不要使用XLS格式,而应使用自定义的快速数据格式来读写表。

在最基本的情况下,只需将列数和行数写入二进制文件,然后一次性写入所有数据。这将非常快,我创建了一个小示例here,该示例仅将300.000 x 40 float32s写入文件并读回。在我的机器上,这大约需要400毫秒和250毫秒(请注意,文件在写入后在高速缓存中很热,在首次读取时可能会花费更长的时间)。

package main

import (
    "encoding/binary"
    "os"

    "github.com/gonutz/tic"
)

func main() {
    const (
        rowCount = 300000
        colCount = 40
    )
    values := make([]float32, rowCount*colCount)
    func() {
        defer tic.Toc()("write")
        f, _ := os.Create("file")
        defer f.Close()
        binary.Write(f, binary.LittleEndian, int64(rowCount))
        binary.Write(f, binary.LittleEndian, int64(colCount))
        check(binary.Write(f, binary.LittleEndian, values))
    }()
    func() {
        defer tic.Toc()("read")
        f, _ := os.Open("file")
        defer f.Close()
        var rows, cols int64
        binary.Read(f, binary.LittleEndian, &rows)
        binary.Read(f, binary.LittleEndian, &cols)
        vals := make([]float32, rows*cols)
        check(binary.Read(f, binary.LittleEndian, vals))
    }()
}

func check(err error) {
    if err != nil {
        panic(err)
    }
}