之前
预估时间:一个星期,每天三四个小时
其中,分词1天,遍历1天,正常计数1天,扩展计数2天,其他2天
之后
实际时间:三天,大约共9个小时
其中,计数器Counter:2小时,分析器FileAnalyzer:2小时,遍历器Traverser:2小时,扩展计数器ExtendCounter,3小时,程序主函数,20分钟左右。
时间差了这么多,我觉得主要是因为自己错误的估计了工作量。还有就是写代码的过程中出错不断,debug花了大量的时间。
性能优化时间
基本在写代码的时候尽量优化,写成之后,不知道到底如何优化。。如果还能优化的话,就是自己的算法有问题,因为有目前的结果来看,花费时间最多的都是STL的操作。。
用VS的性能分析工具,release模式下,测试了一个100M+的一个样例,跑了40+s,同学用C#写的程序,跑了30-s。而且我是用的C++,这个让人相当的不爽啊。仔细看了下,我的程序的性能瓶颈在map的find上,因为C++里STL 的map使用红黑树实现的,也就是一次查找是O(lgn)的。而同学是用的是C#的Dictionary,是通过hash进行查找的,接近,接近O(1)。所以如果如果想让我的程序跑的比他的快,就需要实现一个C++的hash_map(呃,C++的一些第三方库中应该有实现的,我的版本的程序中没有实现)。
再加:VS里有hash_map,用hash_map替换了原先的map,结果还是比较给力的,30-s,可以跑出结果,性能提升了大约是1/3。。不过C++的hash_map使用要比C#的复杂,如果以stirng作为键的话,需要自己实现hash_compare。关于hash_map,我主要参考了。。
分析结果
学到What
关于C++
STL中map的insert、erase、find,statble_sort(换用hash_map后,改为sort)。
C++的map和Java的map不同,insert一个相同的键,不会更新原有的键的值,而是返回false,更新失败。Java则是会更新原有的键。所以,在C++的map中更新,正确的操作应当是先find那个键,之后直接修改得到的iterator,一般是这样
map.find(key)->second = new_value;
hash_map的一些东西,比如对于非标准结构和自定义的结构,需要自己实现hash_compare等。
关于软件设计
各部分分离,尽量满足OO的要求。这一点,我在写C代码的时候会不自觉的把一些相同的东西抽出来,弄成一个函数。C++就是把一些函数升级成为类。当然抽出来时抽出来了,如何抽得恰到好处,就是软工和OO要学的东西了
其他
刚刚看了几个Shine Team的几个大牛的博客,写的SO激情澎湃,各种不知道的术语、名词,还有神一般的性能,彻底跪了。。
刚刚把自己那个小数据的图换下来了,否则看着那张8s的性能分析,还以为是133M的数据跑出的结果。。