團隊的編程比賽,題目是給一個文本文件,在去掉二十個經常使用詞之後,統計出現頻率前十位的詞。c++
我採用的是哈希表,c++語言實現。編程
1.使用mmap,將內容映射到內存。多線程
2.文本分割,處理邊界條件,在ranges[]中指明每一個區間的開始和結束位置。ide
3.Worker線程中分塊處理,對於每個單詞,在哈希表中相應位置查找,插入。優化
4.Worker線程結束後,獲得了有統計結果的哈希表,將結果進行過濾(去掉20個經常使用單詞),裝入vector中。線程
5.使用std::algorithm中的heap建堆,取出前十個元素。內存
優化get
1.使用mmap而不是fread:fread會先將內容從磁盤拷貝到內存的內核空間,再轉移到用戶態,相比mmap來講,多了一次拷貝.it
2.只採用了一張哈希表,避免多線程之間的合併,插入操做時沒有加鎖,而採用了相似於CAS的原子操做:asm
asm volatile( 「lock;\n\t」 「cmpxchgq %3, %2″ : 「=a」(old) : 「0″(0), 「m」(*p), 「r」(np) : 「memory」);
關於cmpxchgq的介紹能夠看這裏。須要注意的是Intel格式彙編和Linux的AT&T格式不一樣。
3.最後過濾單詞時,先判斷長度,不符合的直接放過,能夠減小比較次數。
總結
1.預處理(映射,分割)佔用了比較長的時間,沒有充分利用CPU,若是分塊讀入並處理,可能效果會更好。
2.最後簡單建了一個巨大的heap來存放過濾後的結果,並建堆。這一步沒有仔細考慮,應該還有更好的優化方案。
3.採用單鏈表處理衝突,該單鏈表只在尾部插入,沒有刪除操做,再加上CAS操做自己的原子性,能夠保證insert操做的原子性,不過貌似這個操做仍是有bug。
4.鎖和系統調用都很消耗時間,在保證正確性的前提下,能不用盡可能不用。