关于软件工程个人作业 Word frequency program 的总结
一、预计花在程序各部分的时间:
(1)对所给命令行参数的判断和处理,看它是否合法、是哪种模式。预计用时20min;
(2)关于目录操作:遍历给定目录下的所有文件,包括子目录和非目录文件。预计用时40min;
(3)对符合格式的文本文件进行读操作,用正则表达式匹配单词,用哈希表存储单词的词频,包括两种模式。 由于这里的“单词”不是传统中的单词,所以有较多细节要处理。
简单模式预计用时2h,扩展模式只要在简单模式的基础上稍加修改,预计用时1h;
(4)词频排序输出,预计用时1h;
(5)对程序的测试与优化,预计用时2h;
(6)对本次作业进行总结,写博客,预计用时2h。
预计花费总时间:9h
二、实际开发完善所用时间
(1)命令行参数判断与处理:约15min;
(2)递归遍历目录下的文件和文件夹:约50min;
(3)词频统计方面,先简单学习了基本正则表达式和哈希表的用法,并且后来把简单模式和扩展模式合并在一个函数中实现。期间遇到了很多很多小问题花费了较多时间。
实际用时大约3h;
(4)由于不仅要求按词频降序排列,词频相同者还要按基于ascll码的字典序排列,故花费了不少时间,约1.5h;
(5)顺利实现要求的功能后,着手进行代码的整合与优化,用时约1h;
进行测试与性能分析,约用时1.5h;
(6)进行程序的容错性处理,约用时30min;
(7)写博客,完成作业总结,约用时2.5h。
实际用时总计约 11h
三、程序性能分析
由于第一次接触到VS2012的程序分析工具,不太熟悉,花了些时间。用性能分析工具运行程序时,可能是因为要统计个函数执行时间、CPU占用率等指标,程序运行时间明显比单纯运行程序所用时间长,所以这部分花的时间较多。
性能分析测试文件是一个392k的英文txt小说,如下
文件内容中特地加入了一些特殊情况的字符串,如12zone zone12 zone2空间 zone23 zOnE23 等,用以测试程序处理是否正确。
》》》优化概述
通过分析,先优化了代码的逻辑结构,以避免执行一些本来不必要执行的代码。在本程序中,这点很重要,因为程序中会有很多次字符串的比较,特别是文本很大的时候,如果能避免执行一些不必要执行的代码,效率回报很可观。
优化过程中发现,未优化前扩展模式下执行比重最大的函数是正则表达式的Match,简单模式下是String的ToLower,因此尝试自己写个相同功能的函数来替代它们,看是否能提高效率。
》》》详细优化过程
(一)优化代码的逻辑结构(这里是在扩展模式下优化,实际上优化结果对简单模式也有用)
1、以下是分析报告的摘要图:
从上图可以看出,耗时最多的函数是Match函数,合起来达到82.38% .进入函数详细信息,如下图:
从上图可以看出,性能主要损耗在突出显示的两行代码上,这两行代码的功能是分别提取当前单词和已存单词去除数字后缀后的子串,如从windows2000中提取出windows。这里的Match不是我自己写的函数,而是正则表达式的静态函数,其损耗如此之高的一个原因是执行次数太多——每次比较两个单词是否“一样”前都要执行这两句,实际上很多情况下并不需要执行它们。这是代码逻辑结构不合理的结果,改进办法是把这两句放在合适的地方,使得该执行的时候才被执行。
2、第一次优化后的分析报告如下:
从上图可以看出,程序的执行时间从260s减少到了140多s,大大减少了,CPU使用百分率整体上也下降了不少,程序性能有了不少的提高。
两次曲线图比较如下:(扩展模式)
(二)简单模式下的优化
1、优化前的分析报告摘要图如下:
从图可以看出,耗时最大的函数为ToLower,跟踪这个函数,如下图:
图中那行高亮代码的功能是比较两个字符串在大小写无关的情况下是否相同,其中ToLower是String的静态函数,是C#语言自有的。语言越高级效率一般就越低,因此如果要优化的话只能自己写一个相同功能的函数来替代它。于是我抱着试试看的想法通过逐个比较字符串里的字符实现了个isEqual函数来替代该行,看效率是否会有改善。
2、优化后的分析报告图如下:
优化结果令人惊讶。通过前后对比,可以看出最耗时的部分不再是比较两个字符串是否相等(大小写无关)的部分,其比重由原来(ToLower())的75%左右降到了(isEqual())19%左右;更甚,程序运行时间从原来的28s降到了8s多!我搞不懂为什么改个简单的ToLower函数后能下降这么多,觉得不太合理,希望老师看到这里时指点指点。
3、优化前后曲线图比较如下:(简单模式)
比较结果不言而喻。
三、扩展模式下的优化
1、优化前的分析报告摘要图如下
可以看出,耗时比重最大的是函数Match,跟踪该函数,如下图:
时间主要耗费在用Match提取单词除去可能有的数字后缀后的子串上,自写一个函数string subword(string str),实现该提取功能,替代之。
2、优化后的分析报告
优化的结果更加令人惊讶,自己实现的简单的subword函数比正则表达式的Match效率高了非常多,运行时间从110s下降到了12s多,算是真正体会到”编程语言越高级,效率越低“这句话的意义了!
优化前后曲线图对比如下:
四、所用测试用例
(1)所给路径为空文件夹
(2)所给路径不为空文件夹,但该文件夹下含有空的子文件夹
(3)所给路径下含有.txt 或 .cpp 或 .cs 或 .h 格式的空文件
(4)含有大小写不同的“相同单词”,如zone ZonE zoNE
(5)含有少于四个字符开头的字符串,如my car123
(6)含有以数字开头字符串,如 3days
(7)含有各种非数字字母字符的文件,如*,、/~!……^等
(8)含有中间夹杂数字的“单词”,如 from12to
(9)含有大规模文本文件,测试程序是否能顺利运行
(10)针对字典序的测试,如同时含有Mother1 ,abc1;同时含有windows2000,Windows1
五、些许收获些许想法
通过这次作业,我的确学到了一些东西。如哈希表、正则表达式的使用、c#的文件操作等,还有C#的一些其他特性。更重要的,我想应该是结识了vs2012的性能分析工具,发现它真的很强大,对我们来说是个非常有用的工具,如果能好好利用,相信能给我们的编程优化带来很大的帮助!
不过,通过这次作业,也真真切切地体会到相对于C、C++等,C#真的太慢了!
关于这次作业,说说自己的一点看法。课上,不少同学反映说没学过C++、C#,它们的文件操作也没学过、还有可能用到的哈希表或map容器也没学过,vs2012也几乎没用过,更不用说它的性能分析工具的使用了,就算学过也只是蜻蜓点水般,根本不熟悉,你让我们用没基础或有基础但根本不熟悉的语言在一周内写出这个程序,光学习就得有一些时间了,这怎么可以?对此,斗胆谈谈自己的看法,或许会成为众矢之,但我觉得很有必要说一下。大一时,我也常常是这种心态,但后来渐渐受室友的影响“改正”了。我觉得这种想法是不对的,为什么一定要得先前学过了才能做呢?编程写程序不都强调学中做吗,实际上完全可以先找个教程快速入门然后就着手进行编写。这中间有哪些东西不会可以去查阅相关书籍,更甚,现在网络这么便利,完全可以上网去查相关资料,一般都会有解决办法的,学习了解决方法就可以将之运用到你的问题中去,这不就跨越当前的障碍了吗?没有哪个人是什么都懂的,有多少的程序不是通过查资料解决一个又一个的问题最后新鲜出炉的?如果都等学透了才去做,那得有多少的时间投入你说是吗?当然,上网查资料并不是要复制代码,而是通过代码理解学习它的解决思路解决方法,然后加以运用。
这次作业让大多数同学很无奈、很不满,这是事实,这说明了要求真的不甚合理,有改进的必要性。但是我认为不合理之处不在于如上所述需要用到不少没学过的东西而在于时间的要求上。说实话,一周的时间真的偏少了,因为我们不仅要实现程序还要现学不少的东西,此外,我们还有其他科目,并且这是开学第一周,事儿比较多,我们根本不可能把时间集中在这个作业上。其结果是我们很多人都不能按时完成,就算有一些人按时完成了,那也是几乎通宵奋战的结果,截止日期前夜,有多少个宿舍灯火通明?这种仓促之中赶出的作业的质量、性能应该相当地不乐观。我想,这或许不符合布置作业的本意吧。