2012-04-29 3 views
2

Как часть моего Go учебник, я пишу простую программу, подсчитывая слова в нескольких файлах. У меня есть несколько go подпрограмм для обработки файлов и создания map[string]int, рассказывающих, сколько встречающихся слов найдено. Затем карта отправляется на сокращение подпрограммы, которая объединяет значения в одну карту. Звучит довольно просто и выглядит как идеальная задача для Go!Go: обширное использование памяти при повторном использовании клавиш карты

У меня есть около 10 тыс. Документов с 1,6 млн уникальных слов. То, что я нашел, - это использование моей памяти, которая быстро растет и постоянно работает при запуске кода, и у меня заканчивается нехватка памяти примерно в половине способов обработки (12 ГБ, 7 ГБ бесплатно). Так что да, он использует гигабайты для этого небольшого набора данных!

Попытка выяснить, где лежит проблема, я обнаружил, что данные по сбору и агрегации редуктора виноваты. А вот код:

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 или, вернее, с собой?

Спасибо!

ответ

2

Как выглядит ваш код, который превращает файлы в строки? Я искал бы проблему там. Если вы конвертируете большие блоки (целые файлы, возможно?) В строки, а затем разрезаете их на слова, тогда вы закрепляете весь блок, если вы сохраняете одно слово. Попробуйте сохранить блоки как [] байт, нарезая их словами, а затем преобразовывая слова в тип строки отдельно.

+0

Престижность для интуиции, это была сама проблема! Я забыл, что я должен теперь подумать обрезать ломтиками. Я конвертировал каждый файл в строку в самом начале, так как нашел быстрее, но не понял, что это неправильно. Спасибо за помощь! – tomasz

+0

@tomasz. Для общего потребления памяти вашей программы должно быть невозможно радикально превысить сумму файлов, считанных программой. Я предполагаю, что каждый отдельный файл читается только один раз. Каков общий размер этих 10 тыс. Документов? Является ли более 1 ГБ? –

+0

@ Атом, это правильно, документы составляют более 5 ГБ. – tomasz

Смежные вопросы