中间件团队组织的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#词频统计优化思路