Go:重用地图键时大量使用内存

时间:2012-04-29 22:58:55

标签: memory map go

作为我的 Go 教程的一部分,我正在编写跨多个文件的简单程序计数单词。我有一些 go例程用于处理文件并创建map[string]int,告知已找到特定单词的出现次数。然后将地图发送到简化例程,该例程将值聚合到单个映射。听起来非常简单,看起来像Go的完美(map-reduce)任务!

我有大约10k的文件,有160万个独特的单词。我发现我的内存使用量在运行代码时快速且持续增长,并且我在大约一半的处理时耗尽内存(12GB盒,7GB免费)。所以是的,它为这个小数据集使用千兆字节!

试图找出问题所在,我发现减速器收集和汇总数据是罪魁祸首。代码如下:

func reduceWords (input chan map[string]int, output chan int) {
  total := make(map[string]int)
  for wordMap := range input {
    for w, c := range wordMap {
      total[w] += c
    }
  }      
  output <- len(total)
}

如果我从上面的示例中删除了地图,则内存保持在合理的限制范围内(几百兆字节)。我发现的是,取一个字符串的副本也解决了问题,即下面的样本不会占用我的记忆:

func reduceWords (input chan map[string]int, output chan int) {
  total := make(map[string]int)
  for wordMap := range input {
    for w, c := range wordMap {
      copyW := make([]byte, len(w)) // <-- will put a copy here!
      copy(copyW, w)
      total[string(copyW)] += c
    }
  }  
  output <- len(total)
}

当我直接使用该值时,是否有可能在每次迭代后都没有销毁wordMap实例? (作为一名C ++程序员,我对GC的直觉有限。)它是否是理想的行为?难道我做错了什么?我应该对 Go 或者对自己感到失望吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

您的代码将文件转换为字符串是什么样的?我会在那里寻找一个问题。如果要将大块(可能是整个文件?)转换为字符串,然后将它们切换成单词,那么如果保存任何一个单词,则会固定整个块。尝试将块保持为[]字节,将它们切换为单词,然后将单词转换为字符串类型。