作为我的Go教程的一部分,我正在编写简单的程序来计算多个文件中的单词。我有一些go例程,用于处理文件和创建map[string]int告诉已发现特定单词的次数。然后将映射发送到约简例程,该例程将值聚合到单个映射中。听起来很简单,看起来像Go的完美任务(减少地图操作)!
我大约有1万个文档,其中包含160万个唯一单词。我发现我的内存使用量在运行代码时快速且持续地增长,而我的内存用完了大约一半的处理时间(12GB盒装,7GB可用空间)。所以是的,它为这个小数据集使用了千兆字节!
试图找出问题出在哪里,我发现归咎于reduceer收集和汇总数据。代码如下:
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还是对自己感到失望?
胡说叔叔
相关分类