Golang 读取 csv 消耗的内存空间是磁盘空间的 2 倍以上

Dev*_*kla 1 csv go

我正在使用 Golang 将大量 CSV 文件加载到结构中。结构是

type csvData struct {
    Index   []time.Time
    Columns map[string][]float64
}    
Run Code Online (Sandbox Code Playgroud)

我有一个解析器使用:

csv.NewReader(file).ReadAll()
Run Code Online (Sandbox Code Playgroud)

然后我迭代行,并将值转换为其类型:time.Timefloat64

问题是这些文件在磁盘上占用了 5GB 空间。一旦我将它们加载到内存中,它们就会消耗 12GB!

我使用ioutil.ReadFile(path)后发现,正如预期的那样,这几乎与磁盘上的大小完全相同。

这是我的解析器的代码,为了可读性省略了错误,如果您可以帮助我排除故障:

csv.NewReader(file).ReadAll()
Run Code Online (Sandbox Code Playgroud)

我尝试通过在函数调用结束时将columnData和设置为 nil 来进行故障排除,但没有任何变化。reader

icz*_*cza 5

这并不奇怪。您的磁盘上只有 CSV 文本的字符(字节)。当您将它们加载到内存中时,您就可以根据文本创建数据结构。

例如,一个float64值在内存中需要64位,即:8个字节。如果您有一个输入文本"1",则为 1 个单字节。然而,如果您创建一个float64等于 的值1,它仍然会消耗 8 个字节。

此外,string存储的 s 具有字符串标头 ( reflect.StringHeader),该标头是 2 个整数值(在 64 位架构上为 16 个字节),并且该标头指向实际的字符串数据。有关详细信息,请参阅Golang 中的字符串内存使用情况

切片也是类似的数据结构:reflect.SliceHeader. 标头由 3 个整数值组成,即使切片中没有元素,在 64 位架构上也是 24 字节。

在此之上的结构可能具有填充(字段必须与某些值对齐),这再次增加了开销。有关详细信息,请参阅规格:尺寸和对齐保证

Go 映射是哈希映射,它又具有相当大的开销,有关详细信息,请参阅为什么切片值有时会过时,但映射值却不会?,有关内存使用情况,请参阅golang 映射保留多少内存?