团队的编程比赛,题目是给一个文本文件,在去掉二十个经常使用词之后,统计出现频率前十位的词。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.锁和系统调用都很消耗时间,在保证正确性的前提下,能不用尽可能不用。