在 Python 中测量实例化 + 方法执行时间
Measure instantiation + method execution time in Python
我有一个 Python class 并且想测量实例化 class 并执行一个方法所花费的时间,例如 100,运行 s.
我注意到第一个 运行 比连续的 运行 花费的时间要长得多。我假设这是由分支预测引起的,因为输入没有改变。但是,我想测量“从头开始”花费的时间,即没有分支预测的好处。请注意,在这种情况下构建真实的输入很困难,因此 运行 必须在相同的输入上执行。
为了解决这个问题,我尝试在每个 运行 上创建一个新对象并删除旧对象:
import time
class Myobject:
def mymethod(self):
"""
Does something complex.
"""
pass
def benchmark(runs=100):
"""
The argument runs corresponds to the number of times the benchmark is to be executed.
"""
times_per_run = []
r = range(runs)
for _ in r:
t2_start = time.perf_counter()
# instantiation
obj = Myobject()
# method execution
obj.mymethod()
del obj
t2_stop = time.perf_counter()
times_per_run.append(t2_stop-t2_start)
print(times_per_run)
benchmark(runs=10)
执行此代码表明每个 运行 的平均时间变化很大。第一个 运行 持续花费更长的时间。跨多个 运行 进行基准测试时,如何消除分支预测的好处?
为了避免预热的好处(关于 post 的评论),我使用 subprocess
模块单独触发 运行s,同时测量每个 [=] 的时间17=] 然后汇总结果:
def benchmark(runs=100):
times_per_run = []
command = "python3 ./myclass.py"
for _ in range(runs):
t1_start = time.perf_counter()
subprocess.run([command], capture_output=True, shell=True, check=False)
t1_stop = time.perf_counter()
times_per_run.append(t1_stop - t1_start)
logging.info(f"Average time per run: {sum(times_per_run) / runs}")
benchmark()
这会产生稳定的结果。
我有一个 Python class 并且想测量实例化 class 并执行一个方法所花费的时间,例如 100,运行 s.
我注意到第一个 运行 比连续的 运行 花费的时间要长得多。我假设这是由分支预测引起的,因为输入没有改变。但是,我想测量“从头开始”花费的时间,即没有分支预测的好处。请注意,在这种情况下构建真实的输入很困难,因此 运行 必须在相同的输入上执行。
为了解决这个问题,我尝试在每个 运行 上创建一个新对象并删除旧对象:
import time
class Myobject:
def mymethod(self):
"""
Does something complex.
"""
pass
def benchmark(runs=100):
"""
The argument runs corresponds to the number of times the benchmark is to be executed.
"""
times_per_run = []
r = range(runs)
for _ in r:
t2_start = time.perf_counter()
# instantiation
obj = Myobject()
# method execution
obj.mymethod()
del obj
t2_stop = time.perf_counter()
times_per_run.append(t2_stop-t2_start)
print(times_per_run)
benchmark(runs=10)
执行此代码表明每个 运行 的平均时间变化很大。第一个 运行 持续花费更长的时间。跨多个 运行 进行基准测试时,如何消除分支预测的好处?
为了避免预热的好处(关于 post 的评论),我使用 subprocess
模块单独触发 运行s,同时测量每个 [=] 的时间17=] 然后汇总结果:
def benchmark(runs=100):
times_per_run = []
command = "python3 ./myclass.py"
for _ in range(runs):
t1_start = time.perf_counter()
subprocess.run([command], capture_output=True, shell=True, check=False)
t1_stop = time.perf_counter()
times_per_run.append(t1_stop - t1_start)
logging.info(f"Average time per run: {sum(times_per_run) / runs}")
benchmark()
这会产生稳定的结果。