2012-04-29 23 views
2

作爲我的的一部分轉到教程,我正在編寫跨多個文件的簡單程序計數單詞。我有幾個去例行程序用於處理文件和創建map[string]int,告知發現了多少特定單詞。然後將地圖發送到縮小例程,該例程將值彙總到單個地圖。聽起來很直接,看起來像Go的完美(地圖減少)任務!轉:當重複使用地圖鍵時,內存佔用大量使用

我有大約10萬個文件,有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的直覺有限。)這是否是可取的行爲?難道我做錯了什麼?我應該對還是對我自己感到失望?

謝謝!

回答

2

你的代碼是什麼樣子,將文件轉換爲字符串?我會在那裏尋找一個問題。如果要將大塊(整個文件可能?)轉換爲字符串,然後將這些塊切分爲單詞,那麼如果保存任何一個單詞,則會鎖定整個塊。嘗試將塊保留爲[]字節,將它們分成單詞,然後將單詞轉換爲單獨的字符串類型。

+0

直覺的榮譽,它本身就是問題!我忘了我必須從現在開始思考。我在開始時將每個文件轉換爲字符串,因爲我發現它更快,但沒有意識到這是錯誤的。感謝幫助! – tomasz

+0

@tomasz程序的總內存消耗量應該不可能超過程序讀取的文件大小的總和。我假設每個不同的文件只讀一次。這些10k文件的總大小是多少?是超過1 GB? – 2012-04-30 05:13:10

+0

@Atom,這是正確的,文件總共超過5GB。 – tomasz