0

我试图减少下面代码的内存占用,这只是初始化我需要的数据,然后执行一组操作。

需要预先分配。

func bToMb(b uint64) uint64 {
    return b / 1024 / 1024
}

func printMemUsage() {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    // For info on each, see: https://golang.org/pkg/runtime/#MemStats
    fmt.Println("\n---")
    fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
    fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
    fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
    fmt.Printf("\tNumGC = %v\n", m.NumGC)
    fmt.Println("---")
}

type Container struct {
    key string
    left  []*Container
    right []*Container
}

func main() {
    var start = time.Now()
    const count = 100_000_000
    const steps = 500
    const childCount = 50
    var m = make(map[string]*Container, count)
    fmt.Printf("map initialized: %v\n", time.Since(start))
    for i := 0; i < count / (childCount * 2); i++ {
        if i % (count / steps) == 0 {
            fmt.Printf("i = %v\n", i)
            printMemUsage()
        }
        for j := 0; j < childCount * 2; j++ {
            var key = fmt.Sprintf("%d:%d", i, j)
            m[key] = &Container{
                key: key,
                left: make([]*Container, 0, childCount),
                right: make([]*Container, 0, childCount),
            }
        }
    }
    fmt.Println("done!")
    printMemUsage()
}

我遇到的一个问题是初始化甚至无法完全执行......这就是我在执行上面的代码时得到的:

GOROOT=C:\Go #gosetup
GOPATH=C:\Users\User\go #gosetup
C:\Go\bin\go.exe build -o C:\Users\User\AppData\Local\Temp\___180go_build_main_go.exe C:\Users\User\Repos\go-playground\main.go #gosetup
C:\Users\User\AppData\Local\Temp\___180go_build_main_go.exe #gosetup
map initialized: 383.0352ms
i = 0

---
Alloc = 3536 MiB    TotalAlloc = 3536 MiB   Sys = 3658 MiB  NumGC = 0
---
i = 200000

---
Alloc = 20983 MiB   TotalAlloc = 20999 MiB  Sys = 22673 MiB NumGC = 3
---
runtime: VirtualAlloc of 8192 bytes failed with errno=1455
fatal error: out of memory

runtime stack:
runtime.throw(0xa4b84e, 0xd)
    C:/Go/src/runtime/panic.go:1116 +0x79
runtime.sysUsed(0xc82440e000, 0x2000)
    C:/Go/src/runtime/mem_windows.go:83 +0x22e
runtime.(*mheap).allocSpan(0xb07980, 0x1, 0x230330b2c00, 0xb22508, 0x23033e6c358)
    C:/Go/src/runtime/mheap.go:1276 +0x3c7
runtime.(*mheap).alloc.func1()
    C:/Go/src/runtime/mheap.go:907 +0x6b
runtime.systemstack(0x0)
    C:/Go/src/runtime/asm_amd64.s:370 +0x6b
runtime.mstart()
    C:/Go/src/runtime/proc.go:1116

goroutine 1 [running]:
runtime.systemstack_switch()
    C:/Go/src/runtime/asm_amd64.s:330 fp=0xc3acf25c20 sp=0xc3acf25c18 pc=0x9d2da0
runtime.(*mheap).alloc(0xb07980, 0x1, 0xc0dd11012c, 0x63)
    C:/Go/src/runtime/mheap.go:901 +0x88 fp=0xc3acf25c70 sp=0xc3acf25c20 pc=0x995fa8
runtime.(*mcentral).grow(0xb1ac30, 0x0)
    C:/Go/src/runtime/mcentral.go:506 +0x88 fp=0xc3acf25cb8 sp=0xc3acf25c70 pc=0x986e08
runtime.(*mcentral).cacheSpan(0xb1ac30, 0x23033e6c358)
    C:/Go/src/runtime/mcentral.go:177 +0x3e5 fp=0xc3acf25d30 sp=0xc3acf25cb8 pc=0x986b85
runtime.(*mcache).refill(0x22fd4b50e58, 0x2c)
    C:/Go/src/runtime/mcache.go:142 +0xb5 fp=0xc3acf25d50 sp=0xc3acf25d30 pc=0x9864f5
runtime.(*mcache).nextFree(0x22fd4b50e58, 0xc00003b02c, 0x0, 0xc3acf25dc8, 0x9df265)
    C:/Go/src/runtime/malloc.go:880 +0xa5 fp=0xc3acf25d88 sp=0xc3acf25d50 pc=0x97c665
runtime.mallocgc(0x1a0, 0xa2b460, 0xc8243f6801, 0xc0dd110000)
    C:/Go/src/runtime/malloc.go:1061 +0x894 fp=0xc3acf25e28 sp=0xc3acf25d88 pc=0x97d0b4
runtime.makeslice(0xa2b460, 0x0, 0x32, 0x2)
    C:/Go/src/runtime/slice.go:98 +0x78 fp=0xc3acf25e58 sp=0xc3acf25e28 pc=0x9b81b8
main.main()
    C:/Users/User/Repos/go-playground/main.go:102 +0x255 fp=0xc3acf25f88 sp=0xc3acf25e58 pc=0xa230b5
runtime.main()
    C:/Go/src/runtime/proc.go:204 +0x209 fp=0xc3acf25fe0 sp=0xc3acf25f88 pc=0x9a89c9
runtime.goexit()
    C:/Go/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc3acf25fe8 sp=0xc3acf25fe0 pc=0x9d4b61

Process finished with exit code 2

我怎样才能避免fatal error: out of memory


优化 1:移至uint32键(而不是string):

type UInt32Container struct {
    key uint32
    left  []uint32
    right []uint32
}

优化二:剥离容器的key:

type UInt32Container struct {
    left  []uint32
    right []uint32
}

优化 3:使用 2D uint32 数组存储:


上述这些优化仍然不够。

4

0 回答 0