python代码运行时间统计

以下方法分别针对 代码块、代码程序文件、 函数 进行性能计时统计

一、time.time() 或者 datetime.datetime.now()

返回当前时间的时间戳 如 1524302633.980187
两次时间相减,代码运行所需的 挂钟时间,也就是命令开始执行到结束的时间。

import time
start = time.time()
print("Hello World")
time.sleep(2)
end = time.time()
print(end - start)

输出

Hello World
2.0038700103759766

二、time.clock()

clock() 函数以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。
在win系统下,这个函数返回的是真实时间(wall time),而在Unix/Linux下返回的是CPU时间。

#文件 test.py
import time
start = time.clock()
print("Hello World")
time.sleep(2)
end = time.clock()
print(end - start)

linux 下输出

Hello World
 0.00020299999999999485

time.clock(),python 3.3版本以后这个函数被废弃了,但是这个函数仍然可以使用。

三、time

在linux下对整个程序做计时统计
time python test.py 如果time 命令报错,可以使用/usr/bin/time 而不是time

/usr/bin/time -p python test.py

输出内容
real 0m2.057s
user 0m0.033s
sys 0m0.011s

real 记录了整体的耗时
user 记录了 CPU花在任务上的时间,但不包括内核函数花费的时间
sys 记录了内核函数花费的时间
对user和sys 相加就得到了CPU总共花费的时间。而这个时间和real的差则有可能是花费在等待IO上。

可以打开–verbose开关来获得更多输出信息
/usr/bin/timee --verbose python test.py

四、cProfile

cProfile:基于lsprof的用C语言实现的扩展应用,运行开销比较合理,适合分析运行时间较长的程序,推荐使用这个模块;
python -m cProfile test.py python -m cProfile -o profile.stats test.py 生成一个统计文件然后通过python进行分析
import pstats
p = pstats.Stats(“profile.stats”)
p.print_stats()

Hello World
0.00010600000000000193
         8 function calls in 2.005 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.005    2.005 test.py:3(<module>)
        1    0.000    0.000    2.005    2.005 {built-in method builtins.exec}
        2    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        2    0.000    0.000    0.000    0.000 {built-in method time.clock}
        1    2.005    2.005    2.005    2.005 {built-in method time.sleep}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

ncalls:表示函数调用的次数;
tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
percall:(第一个percall)等于 tottime/ncalls;
cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
filename:lineno(function):每个函数调用的具体信息;

用runsnakerun 对cProfile的输出进行可视化
pip install runsnake 来安装,需要wxPython,在virtualenv下安装会比较麻烦。没试过,记录下。
来自书籍《python高性能编程》

五、 timeit

from timeit import timeit

timeit('math.sqrt(2)', 'import math', number=100000)

六、装饰器–对函数进行计时统计

定义装饰器timethis
将装饰器放在函数定义之前,就能得到对应函数的计时信息

from functools import wraps
import time

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 ts():
    time.sleep(2)
    print("Hello World")

ts()

输出
Hello World
main.ts : 2.0007375059940387

七、用line_profiler进行逐行分析

用cProfile找到需要分析的函数,然后用line_profiler对函数进行分析。line_profiler可以帮你一行一行分析函数性能
pip install line_profiler

运行kernprof 逐行分析被修饰函数的CPU开销
kernprof.py -l -v test.py -v 显示输出
-l 代表逐行分析而不是逐函数分析

Total Time:测试代码的总运行时间
Hits:表示每行代码运行的次数
Time:每行代码运行的总时间
Per Hits:每行代码运行一次的时间
% Time:每行代码运行时间的百分比

备注

使用time.perf_counter() 能够提供给定平台上精度最高的计时器,但是,它计算的仍然是时钟时间,很多因素会影响到它的精确度,比如机器负载。
如果你对于执行时间更感兴趣,使用time.process_time() 来代替它。