Как часть моего 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 или, вернее, с собой?
Спасибо!
Престижность для интуиции, это была сама проблема! Я забыл, что я должен теперь подумать обрезать ломтиками. Я конвертировал каждый файл в строку в самом начале, так как нашел быстрее, но не понял, что это неправильно. Спасибо за помощь! – tomasz
@tomasz. Для общего потребления памяти вашей программы должно быть невозможно радикально превысить сумму файлов, считанных программой. Я предполагаю, что каждый отдельный файл читается только один раз. Каков общий размер этих 10 тыс. Документов? Является ли более 1 ГБ? –
@ Атом, это правильно, документы составляют более 5 ГБ. – tomasz