# -*- encoding: utf-8 -*-
from bisect import bisect_left
from cProfile import Profile
from pstats import Stats
from random import randint
'''
第58条: 先分析性能,然后再优化
关键:
1 性能问题
建议: 优化程序之前先分析性能
性能分析工具: profiler,可以计算程序中某部分执行时间在总体时间中的占比
主要有: cProfile, profile
cProfile: c语言编写的profile,合理运行开销,推荐
profile: 纯python模块,本身占据时间,不推荐
2 cProfile模块
cProfile.Profile.run(comand, fileName=None, sort=-1)
作用: 该函数接收一个单独的参数,并可以被传递到exec()方法,并
添加一个可选的文件名称。
cProfile.Profile.runcall(func, *args, **kwargs)
作用: 通过runcall方法运行定义的函数func
3 pstats模块
pstats.Stats(*filename or profile, stream=sys.stdout)
作用:
pstats.Stats.strip_dirs()
作用: 去除文件名前的路径信息,减少体积
pstats.Stats.sort_stats('cmulative')
作用: 最重要的函数,用来排序profile的输出
pstats.Stats.print_stats(*restrictions)
作用: 把Stats报表输出到stdout
pstatus.Stats.print_callers(*restrictions)
作用: 输出调用了指定的函数的函数相关信息
统计结果样例输出:
20003 function calls in 1.312 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.312 1.312 /home/discovery/driver58.py:80(<lambda>)
1 0.004 0.004 1.312 1.312 /home/discovery/driver58.py:62(insertSort)
10000 1.289 0.000 1.308 0.000 /home/discovery/driver58.py:69(insertValue)
9992 0.019 0.000 0.019 0.000 {method 'insert' of 'list' objects}
8 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
解释:
ncalls: 函数在性能分析期间的调用次数
tottime: 执行该函数所花费的总秒数,本函数因调用其他函数所耗费的时间,不记入在内
tottime percall: 每次调用该函数所花的平均秒数, 本函数因调用其他
函数所耗费的时间,不记入在内。此值等于totime与ncalls相除的商
cumtime:执行该函数及其中的全部函数调用操作,所花的总秒数
cumtime percall: 每次执行该函数及其中全部函数调用操作,所花费的平均秒数。
此值等于cumtime与ncalls相除的商。
4 总结
性能分析时应该使用cProfile模块,调用该cProfile对象的runcall方法
来分析程序的性能,通过pstats.Stats对象来筛选处性能分析数据。
参考:
[1] Effectiv Python 编写高质量Python代码的59个有效方法
[2] https://blog.csdn.net/weixin_40304570/article/details/79459811
[3] https://docs.python.org/2.7/library/profile.html#module-cProfile
[4] https://docs.python.org/2.7/library/profile.html#module-pstats
[5] https://blog.csdn.net/u010453363/article/details/78415553?utm_source=blogxgwz9
'''
def insertSort(data):
result = []
for value in data:
insertValue(result, value)
return result
def insertValue(array, comparedValue):
# for i, value in enumerate(array):
# if value > comparedValue:
# array.insert(i, comparedValue)
# return
# array.append(comparedValue)
i = bisect_left(array, comparedValue)
array.insert(i, comparedValue)
def validInsertSort():
maxValue = 10 ** 4
data = [randint(0, maxValue) for _ in range(maxValue)]
validProfile = lambda: insertSort(data)
profiler = Profile()
profiler.runcall(validProfile)
stats = Stats(profiler)
stats.sort_stats('cumulative')
stats.print_callers()
stats.print_stats()
def process():
validInsertSort()
if __name__ == "__main__":
process()