【问题标题】:Allocation error: runtime: out of memory分配错误:运行时:内存不足
【发布时间】:2017-11-23 03:45:01
【问题描述】:

我写了这段代码:

package main

import (
    "log"
)

func main() {
    var c []int64
    for i := 0; i < 100; i++ {
        c = make([]int64, 10000000000)
        log.Println(len(c))
    }
}

此代码内存不足:fatal error: runtime: out of memory

在每次迭代中,c 将被分配一个新切片。所以前一个切片是不可访问的。为什么 GC 似乎没有收集到无法访问的内存?

【问题讨论】:

  • 80 GB 内存!?
  • @icza:这不是重复的。这是过度分配的情况,尝试在一次分配中分配 80GB,但立即失败:fatal error: runtime: out of memory。正式而言,要成为重复项,答案必须相同。在这种情况下,答案是进行合理大小的分配。在您的回答中,这是对 GC 空闲内存机制的解释,虽然很有趣,但并不能解决这个问题。 .
  • @peterSO 这就是为什么我只写“相关”而不是“重复”。
  • 尝试运行下一条命令ulimit -c unlimited

标签: go garbage-collection


【解决方案1】:

每个c = make([]int64, 10000000000 都试图分配 80GB(8 * 10,000,000,000 字节)的内存。使用合理大小的分配(相对于实际内存的大小),一切都按预期工作。例如,

package main

import (
    "fmt"
    "log"
    "runtime"
)

func main() {
    var ms runtime.MemStats
    runtime.ReadMemStats(&ms)
    fmt.Println(ms.TotalAlloc, ms.Alloc)
    var c []int64
    for i := 0; i < 100; i++ {
        c = make([]int64, 400000000)
        log.Println(len(c), i)
    }
    runtime.ReadMemStats(&ms)
    fmt.Println(ms.TotalAlloc, ms.Alloc)
}

输出:

67032 67032
2017/11/23 01:13:08 400000000 0
2017/11/23 01:13:09 400000000 1
2017/11/23 01:13:09 400000000 2
2017/11/23 01:13:09 400000000 3
2017/11/23 01:13:10 400000000 4
<<SNIP>>
2017/11/23 01:13:43 400000000 95
2017/11/23 01:13:43 400000000 96
2017/11/23 01:13:43 400000000 97
2017/11/23 01:13:44 400000000 98
2017/11/23 01:13:44 400000000 99
320000171152 88168

您尝试为 c 分配 80,000,000,000 字节。我将它减少到更合理的 3,200,000,000 字节。循环分配了 100 次,总共 320,000,171,152 字节,垃圾收集器通过重用内存来处理这些字节。 GC 正在工作。

【讨论】:

  • 你改变了“c”的大小。我的意思是每次迭代内存大小都可以。但是如果循环100次,内存就不够了。在每次迭代中,最后一个切片都无法到达,我认为它应该由 GC 收集。但事实并非如此。那为什么呢?
  • 你没有道理。你有多少内存?
猜你喜欢
  • 1970-01-01
  • 2011-01-11
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
相关资源
最近更新 更多