在原书此章中介绍了四种情况的解决方案:
- 对整个程序做计时统计
- 对函数进行性能分析
- 对语句块进行计时统计
- 对短小代码块做性能统计
1.对整个程序做计时统计
通常使用UNIX下的time命令:
bash % time python3 someprogram.py
如果想针对程序的行为产生一份详细的报告,那么可以使用cProfile模块:
bash % python3 -m cProfile someprogram.py
2.对函数进行性能分析
可以使用装饰器来完成:
# -*- coding: utf-8 -*-
import time
from functools import wraps
# 直接来自Cookbook,这个函数也是个闭包函数。
def timethis(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter() # 平台上精度最高的计时器
r = func(*args, **kwargs)
end = time.perf_counter()
print('{}.{}:{}'.format(func.__module__, func.__name__, end - start))
return r
return wrapper
@timethis
def sumit(x): # 自己编的
n = 0
s = 0
while n < x:
n += 1
s += n
print(s)
if __name__ == '__main__':
sumit(10000)
PS:上面timethis是一个闭包函数,说起闭包函数,它的作用是保存函数的状态信息,使函数的局部变量信息依然可以保存下来。
3.对语句块进行计时统计
可以定义一个上下文管理器:
# -*- coding: utf-8 -*-
import time
from contextlib import contextmanager
# 来自Cookbook原书
@contextmanager
def timeblock(lable):
strat = time.perf_counter()
try:
yield
finally:
end = time.perf_counter()
print('{}: {}'.format(lable, end-strat))
with timeblock('Counting'):
n = 10000000
while n > 0:
n -= 1
4.对短小代码块做性能统计
timeit模块
timeit会执行第一个参数中指定的语句100万次,然后计算时间。第二个参数是一个配置字符串,在运行测试之前会先执行以设定好环境。如果需要修改迭代的次数,只需要提供一个number参数即可。
解决方案中使用的函数time.perf_counter()能够提供给定平台上精度最高的计时器。但是,它的计算仍然是墙上时间(wall-clock time),这会受到不同因素的影响,例如机器当前的负载。
相对于墙上时间,我们更感兴趣的是进程时间,那么可以使用time.process_time()来替代。
网友评论