20180925-3 效能分析
此作业的要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2145
程序地址:https://git.coding.net/tianl364/count_words.git
对上周作业中的功能4 (仅由文件重定向读入,不由控制台读入) 做效能分析,以[https://coding.net/u/younggift/p/word_count_demo/git/blob/master/war_and_peace.txt]为输入数据。
要求0 以 战争与和平 作为输入文件,重读向由文件系统读入。连续三次运行,给出每次消耗时间、CPU参数。
进入文件所在目录,打开控制台,输入:
1 ptime wf -s < war_and_peace.txt
连续三次运行结果如下:
消耗时间汇总:
第一次运行时间 | 0.659 s |
第二次运行时间 | 0.507 s |
第三次运行时间 | 0.510 s |
平均时间 | 0.559 s |
CPU参数: Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 2.50GHz
要求1 给出你猜测程序的瓶颈。你认为优化会有最佳效果,或者在上周在此处做过优化 (或考虑到优化,因此更差的代码没有写出) 。
猜测的瓶颈:使用正则表达式来区分会增加程序的运行时间。
优化思路:通过枚举分割单词的各种符号,然后依次使用replace()方法进行替换。
要求2 通过 profile 找出程序的瓶颈。给出程序运行中最花费时间的3个函数(或代码片断)。要求包括截图。
使用命令行进入程序所在目录后输入以下命令:
1 python -m cProfile -s time wf.py -s < war_and_peace.txt
得到分析结果截图:
ncalls:表示函数调用的次数;
tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
percall:(第一个percall)等于 tottime/ncalls;
cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
filename:lineno(function):每个函数调用的具体信息;
由测试结果可知程序运行中最花费时间的3个函数及运行时间和次数:
函数 | 调用次数 | 运行时间 |
main() | 1 | 0.327 |
getCountByPurText() | 1 | 0.283 |
split() | 1 | 0.058 |
要求3 根据瓶颈,"尽力而为"地优化程序性能。
通过对getCountByPurText()方法中去掉特殊符号方式的变化来进行优化,由之前使用正则表达式的方式换成对分割单词的各种符号进行枚举,然后依次使用replace()方法进行替换。之前使用正则表达式的代码如下:
1 def getCountByPurText(testtext): 2 testtext = re.sub('[^a-zA-Z0-9n]', ' ', testtext) 3 4 #定义词频字典 5 frequency = {} 6 7 #循环判定每个单词频率 8 for word in testtext.split(): 9 if word in frequency: 10 frequency[word] += 1 11 else: 12 frequency[word] = 1 13 frequency = sorted(frequency.items(),key = lambda x:x[1],reverse = True)
改成使用replace()方法后的代码如下:
1 def getCountByPurText(inputText): 2 inputText = inputText.lower() 3 4 for disCh in '!.",)—(#:\n': 5 inputText = inputText.replace(disCh, ' ') 6 7 # 定义词频字典 8 frequencyDic = {} 9 10 for word in inputText.split(): 11 if word in frequencyDic: 12 frequencyDic[word] += 1 13 else: 14 frequencyDic[word] = 1 15 16 # 根据字典的value值排序 17 frequencyDic = sorted(frequencyDic.items(), key=lambda x: x[1], 18 reverse=True)
要求4 再次 profile,给出在 要求1 中的最花费时间的3个函数此时的花费。要求包括截图。
修改后再次profie:
再次测试三次运行时间截图为:
消耗时间再次汇总:
第一次运行时间 | 0.447 s |
第二次运行时间 | 0.455 s |
第三次运行时间 | 0.467 s |
平均运行时间 | 0.456 s |
相比之前的0.559 (s) 节省了 0.103 (s)