中間件團隊組織的Coding4Fun的第三期已經結束,此次參與的同窗很活躍,報名的有20多人,最終有17人在gitlab上提交了代碼。把此次活動以及你們的經驗總結一下。java
任務:python
裏有一個大文本,文件請從 http://10.125.9.144:8000/document.zip 獲取,在解壓後大約有20m(實際比賽時文件是1.1G)。 文本中都是英文單詞,空格以及英文的標點符號: [.,;-~"?'!] (句號,逗號,分號,破折號,波浪號,雙引號,問號,單引號,感嘆號) 請統計出該文本中最常出現的前10個單詞(不區分大小寫)。 請注意,在統計中這20個單詞請忽略(the, and, i, to, of, a, in, was, that, had, he, you, his, my, it, as, with, her, for, on)
說明:linux
1) 編程語言不限 2) 最終的測試機器爲多核環境(單機) 3) 不得藉助外部服務(調用遠程服務) 4) 可引用外部框架或庫(限開源) 5) 結果不正確直接淘汰 6) 用時最短者獲勝(前三名有獎) 7) 代碼優雅凝練(明顯比前三名的代碼量少且易懂)而且性能不太離譜,可獲最佳代碼獎
由於這次不限編程語言,爲避免不一樣語言的運行時/虛擬機啓動時間差別,沒有統一的計時方式,計時方式爲在main的入口和出口自行統計。在比賽的機器上(linux系統,16核,8G內存)運行3次,取時間最短的那次作最終成績。c++
最終獲獎結果:git
澗泉:1936ms c++ 子觀:2489ms c++ 雪酒:2565ms c++ 玄胤:2615ms c 平威:2792ms java 劈空:2860ms c++ 遊驥:3207ms java 長源:3220ms java 叔至:3334ms java 寒玄: 4336ms go 娜米: 4分32秒 perl 一行代碼
第一名:澗泉,惟一突破2秒的,獎品是機械鍵盤算法
他採用併發方式,用ConcurrentTrieNode
實現了線程安全的Trie
樹。詳細經驗見:wordcount設計與優化。澗泉同窗很低調,在Coding4Fun的交流羣裏也很沉默,不過看到他blog裏說的,就能體會到一個追求完美的碼農的心態了:編程
程序開始是用JavaConcurrentHashMap實現的。爲了提高性能翻譯成C++,過程可謂大費周折,至關痛苦,我會告訴你我大半夜還在調segmentalfault嗎?數組
第二名:子觀安全
子觀同窗也是一匹黑馬,剛開始用python實現的,成績幾乎墊底;在提交代碼的前一天晚上通宵debug,實現了大逆轉。
子觀的經驗見:coding4fun比賽總結併發
第三名:雪酒
雪酒同窗暑期來阿里實習,8月底選擇了回學校讀研究生,咱們會把T恤寄給你,也歡迎有空回來轉轉。他的經驗以下:
策略1:盡最大的努力減小動態申請內存
理由:在初始實驗之中,我是每分離出一個單詞就要malloc內存,時間就花銷很長,由於這種小內存的分配的時候,系統會好很長的時間,並且容易產生內存碎片,因而我就想到了儘可能減小malloc的使用,在程序實現之中,除了第一次malloc了一個與文件同樣大的內存外,今後沒有使用過malloc函數,還好現在的gcc支持c99,可讓我預先定義動態數組,這樣子我除了那個在堆上的總buffer,其他的存儲變量幾乎都是在棧上,不只僅節約了時間,並且讓我減小了對內存的管理。
策略2:hash表和trie樹同時使用
理由:trie樹的優勢就不用說了,查找是很快的,缺點是比較的明顯,第一,耗內存,第二仍是耗內存,因爲我採用了策略1的策略,因此,我不能再每一個字母節點都malloc內存,我一開始就把個人trie樹大小給定死了的,當trie樹須要節點的時候,就直接按照預先在靜態區分好了的給,若是超過了預先定的數目,那麼就段錯誤了……=。=,因爲trie樹比較耗內存,因此我就不想每一個線程都來一個trie樹,萬一內存使用過多,致使頻繁的換頁那就虧大了。因此,我在主線程中使用的trie樹,其他線程中,使用的是hash表,這樣子就能大規模的減小進程對內存的佔用了(雖然我一口氣吃的內存也是不少),並且trie樹和hash表同時使用還能夠利用trie樹查找快的這麼一個特色(其實如今也不能肯定trie樹是否能比hash快)。
策略3:待排序的數組去除掉無用的,空的節點
理由:如果使用hash表,我最後排序的時候中間會出現不少的空的節點,把這些空節點一塊兒算進來進行排序的話會有一部分排序是無心義的,要是一開始使用沒有無心義的節點的數組,那麼就能夠減小沒必要要的循環。
第四名:玄胤
玄胤同窗是利用openMP的並行庫+無鎖hashtable來實現的,詳見:c4f玄胤總結,玄胤同窗除了會寫代碼,還會彈彈琴什麼的,文藝青年一枚
簡潔代碼獎:娜米
娜米是這次比賽裏惟一的女生,很偷懶的就用了一行perl程序解決了,雖然效率差了幾個數量級,但聽說娜米妹子也是精通算法的,只是此次比賽沒投入精力。娜米憑她的古靈精怪得到了最簡潔代碼獎,但願下次有更多的妹子參與。
此次比賽很熱鬧,沒有語言的限制,C/C++,Java,Go,Erlang,Python,Perl等百花齊放。最後來一張獲獎者合照(有個別同窗沒在):
補充,長源和平威用java實現的性能也很不錯,大力推薦一下。
長源同窗採用了簡化版的trie,他的分享:coding4fun-詞頻統計的優化思路/
平威選用的hashmap,不過他使用ByteString代替String,詳見:#coding4fun#詞頻統計優化思路