为什么逐行读取文件会占用更多内存?

sam*_*eri 2 memory-management go

我试图读取这种格式的大文件:

a string key, 200 values separated by comma
Run Code Online (Sandbox Code Playgroud)

并将其写入地图。

我写了这段代码:

package main

import (
    "bufio"
    "unsafe"
    "fmt"
    "log"
    "os"
    "runtime"
    "strings"
)

func main() {

    file, err := os.Open("file_address.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    mp := make(map[string]float32)
    var total_size int64 = 0
    scanner := bufio.NewScanner(file)
    var counter int64 = 0

    for scanner.Scan() {
        counter++
        sliced := strings.Split(scanner.Text(), ",")
        mp[sliced[0]] = 2.2
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
    fmt.Printf("loaded: %d. Took %d Mb of memory.", counter, total_size/1024.0/1024.0)
    fmt.Println("Loading finished. Now waiting...")

    var ms runtime.MemStats
    runtime.ReadMemStats(&ms)

    fmt.Printf("\n")
    fmt.Printf("Alloc: %d MB, TotalAlloc: %d MB, Sys: %d MB\n",
        ms.Alloc/1024/1024, ms.TotalAlloc/1024/1024, ms.Sys/1024/1024)
    fmt.Printf("Mallocs: %d, Frees: %d\n",
        ms.Mallocs, ms.Frees)
    fmt.Printf("HeapAlloc: %d MB, HeapSys: %d MB, HeapIdle: %d MB\n",
        ms.HeapAlloc/1024/1024, ms.HeapSys/1024/1024, ms.HeapIdle/1024/1024)
    fmt.Printf("HeapObjects: %d\n", ms.HeapObjects)
    fmt.Printf("\n")
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

loaded: 544594. Took 8 Mb of memory.Loading finished. Now waiting...

Alloc: 2667 MB, TotalAlloc: 3973 MB, Sys: 2831 MB
Mallocs: 1108463, Frees: 401665
HeapAlloc: 2667 MB, HeapSys: 2687 MB, HeapIdle: 11 MB
HeapObjects: 706798

Done!
Run Code Online (Sandbox Code Playgroud)

尽管密钥仅占用8Mb,但该程序却占用2.7Gb的内存!似乎sliced永远不会从堆中删除它。我尝试sliced=nil在末尾进行设置for,但没有帮助。我已经读过,如果我将整个文件加载到内存中然后进行拆分,则可以避免此问题,但是我必须逐行读取文件,因为我没有足够的内存来加载一些较大的文件文件。

为什么内存被占用?处理完每一行后如何释放它?

pet*_*rSO 5

For efficient CPU and memory usage,

key := string(bytes.SplitN(scanner.Bytes(), []byte(","), 2)[0])
mp[key] = 2.2
Run Code Online (Sandbox Code Playgroud)