我们常常需要计算某段代码或某个函数的执行时间来进行某种优化或评估,这里提供一些比较Pythonic的方案。

背景

在训练模型或数据处理时,我们常常要评估任务所花费的时间。

计算某段代码的运行时间,通常使用如下方法,

1
2
3
4
5
6
7
import time

start = time.time()
# 需要计时的代码块
# ....
end = time.time()
print("time elapsed", end - start)

不过这样的代码无法复用,对于Python来说,甚至是丑陋的。当然,性能测试作详细的报表,推荐使用cProfile。

接下来提供一些比较Pythonic的方案。

系统计时

不过在这里我们首先要搞明白系统计时的底层的时间函数。

  • time.clock 在Python3.3中被弃用,可以不用管
  • time.time 提供Epoch到目前的计时,两个时间点的差视为实际流逝的时间长度
  • time.perf_counter 可以确保使用系统上面最精确的计时器
  • time.process_time 可以确保只计算所在进程花费的CPU时间,即执行时间。

需要注意,后两个函数提供的数值都是浮点秒数,没有实际以及,需要两个时间点的差值才能获得对应的实际意义。无论如何,计算时差只是近似,因为很多因素会影响到它的精度,例如机器负载等等。

通常情况下,使用time.time计时即可。

对代码片段计时

如果你的代码片段很少,一行就能表达,推荐使用timeit进行性能测试或计时。

1
2
3
4
5
>>> timeit.timeit("list(np.arange(100))", "import numpy as np", number=1000000) # 100w次
5.923853928004974
>>> timeit.timeit("list(range(100))", number=1000000)
0.44624948799901176
>>>

计时器装饰函数

作为上下文管理器,

1
2
3
4
5
6
7
8
9
10
11
import urllib.request as request
from pytimer import Timer

def task(n):
for _ in range(n):
request.urlopen("https://httpbin.org/")

with Timer(label="request url") as timer:
task(5)

print(timer.elapsed)

计时器装饰类方法

1
2
3
4
5
6
7
8
9
import urllib.request as request
from pytimer import Timer

@Timer(label="time url request")
def task(n):
for _ in range(n):
request.urlopen("https://httpbin.org/")

task(1)

计时器装饰类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import urllib.request as request
from pytimer import timethis

class Task:

@timethis(label="time instance method")
def urlopen1(self, url):
request.urlopen(url)

@classmethod
@timethis(label="time class method")
def urlopen2(self, url):
request.urlopen(url)

@staticmethod
@timethis(label="time static method")
def urlopen3(url):
request.urlopen(url)

task = Task()
task.urlopen1("https://httpbin.org/")
task.urlopen2("https://httpbin.org/")
task.urlopen3("https://httpbin.org/")

其他

当然,如果你想测试程序运行所花费的时间并做性能测试作详细的报表,推荐使用cProfile,

1
python3 -m cProfile your_program.py

项目地址

pytimer上面包括使用例子。

总结

转载请包括本文地址:https://allenwind.github.io/blog/11548
更多文章请参考:https://allenwind.github.io/blog/archives/