首页 > 技术文章 > 韩昊20190919-3 效能分析

hanhao970620 2019-09-22 17:25 原文

作业要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/7628]

该作业git地址为:https://e.coding.net/hanhao/hanhaoceshi.git

• 要求0 以 战争与和平 作为输入文件,重读向由文件系统读入。连续三次运行,给出每次消耗时间、CPU参数。

使用命令行进入程序所在文件夹,输入如下命令:

ptime wf -s < war_and_peace.txt

第一次运行:

第二次运行:

第三次运行:

CPU参数:Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz 2.20 GHz

第三次运行时间:2.395s

第三次运行时间:1.816s

第三次运行时间:1.846s

平均运行时间:2.029s

• 要求1 给出你猜测程序的瓶颈。

在定义处理冗余字符函数时,未处理特殊字符,定义两个for循环,但由于for循环中内容都不可或缺,所以在实现原有功能的前提下猜测可以合成一个for循环。

def deal_Redundantwords(string):
    string = string.replace('\n', ' ').replace(',', ' ')
    s1 = list(string)
    num = len(s1)
    s1.append(' ')
    for i in range(num):
        if s1[i] in '."?\')-(;#$%&*!':
            #isalnum检测字符串是否有数组组成
            if str(s1[i - 1].isalnum()) == 'True' and (str(s1[i + 1].isalnum()) == 'True'):
                pass
            else:
                s1[i] = ' '
    for i in range(num):
        if s1[i] in ':':
            if s1[i + 1] == '/':
                pass
            else:
                s1[i] = ' '
    #join连接字符数组
    s = ''.join(s1)

• 要求2 通过 profile 找出程序的瓶颈。

 效能分析步骤:

python -m cProfile -s time wf.py -s < war_and_peace.txt

  使用命令行进入程序所在目录后输入以下命令:

 

由测试结果可知:我的程序最耗时的函数为“dispose_words”(去除冗余字符),“countWordsFrequency”(统计词频)以及main函数,最耗时的代码段为“dispose_words”函数中的“split()”、“join()”方法。

  其中耗时前三为:

    1. “deal_Redundantwords”函数:调用1次,运行时间为0.936s。

    2. “countNumber”函数:调用1次,运行时间为1.436s。

    3. “split()”方法:调用1次,运行时间为0.053s。

• 要求3 根据瓶颈,"尽力而为"地优化程序性能。

由cProfile分析结果可知:程序耗时最久的为“deal_Redundantwords”函数中的“split()”方法、“join()”方法、“lower()”方法、“replace()”方法、“isalnum()”方法,以及“countNumber”函数中的“keys()”方法。

    考虑到上述功能在整个词频统计功能实现中无法避免的要进行遍历,结合要求1中的猜测,可以将“deal_Redundantwords”函数中的“isalnum()”方法与针对“/”的for循环放在一起,即只进行一次遍历。

def deal_Redundantwords(string):
    string = string.replace('\n',' ').replace(',',' ')
    s1 = list(string)
    num = len(s1)
    s1.append(' ')
    for i in range(num):
        if s1[i] in '."?\')-(;#$%&*!':
            if str(s1[i - 1].isalnum()) == 'True' and (str(s1[i + 1].isalnum()) == 'True'):
                pass
            else:
                s1[i] = ' '
        if s1[i] in ':':
            if s1[i + 1] == '/':
                pass
            else:
                s1[i] = ' '
    s = ''.join(s1)
    #print(s)
    return s    

• 要求4 再次 profile,给出在 要求1 中的最花费时间的3个函数此时的花费。要求包括截图。

修改之后再次cProfile,测试结果见下图:

 

对比优化之前可知:

  (1) “deal_Redundantwords”函数:依旧调用1次,运行时间由0.936下降为0.865s。

  (2)  “countNumber”函数:依旧调用1次,运行时间由1.436下降为1.340s。

  (3) “split()”方法:依旧调用1次,运行时间由0.053s下降为0.052s。

再次profile,2018.10.05 21:08连续测试三次运行时间(对应于要求0)结果见下图:

 

第三次运行时间:1.397s

第三次运行时间:1.391s

第三次运行时间:1.391s

平均运行时间:1.393s

CPU参数:Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz 2.20 GHz

对比可知:平均运行时间由2.029s下降为1.393s

• 要求5 程序运行时间。

等待教师的测评。

推荐阅读