Python time.perf_counter 函数
上次修改时间:2025 年 4 月 11 日
本综合指南探讨了 Python 的 time.perf_counter
函数,该函数为基准测试提供最高的可用分辨率计时器。我们将涵盖性能测量、计时比较和实际示例。
基本定义
time.perf_counter
函数以小数秒为单位返回高分辨率性能计数器值。它专为测量短持续时间而设计。
主要特征:最高的可用计时器分辨率、单调递增(始终增加)、不受系统时钟更改的影响,并且是基准测试的理想选择。参考点未定义,因此只有差异才有意义。
基本性能计时
time.perf_counter
的最简单用法是测量代码执行时间。此示例显示了计时函数调用的基本用法。
import time def calculate_sum(n): return sum(range(n)) # Start timer start = time.perf_counter() # Execute function result = calculate_sum(1000000) # Stop timer end = time.perf_counter() # Calculate duration duration = end - start print(f"Calculation took {duration:.6f} seconds") print(f"Result: {result}")
此示例演示如何测量函数的执行时间。perf_counter
提供适合性能测量的高分辨率计时。
:.6f
格式说明符以 6 位小数显示持续时间,以实现微秒精度。
比较多个实现
time.perf_counter
非常适合比较不同的实现。此示例比较了两种求和数字的方法。
import time def sum_with_loop(n): total = 0 for i in range(n): total += i return total def sum_with_builtin(n): return sum(range(n)) n = 1000000 # Time loop implementation start = time.perf_counter() result = sum_with_loop(n) end = time.perf_counter() print(f"Loop: {end - start:.6f} sec") # Time built-in implementation start = time.perf_counter() result = sum_with_builtin(n) end = time.perf_counter() print(f"Built-in: {end - start:.6f} sec")
此模式有助于识别方法之间的性能差异。内置的 sum
通常比 Python 循环更快。
由于系统可变性,可能需要多次运行才能获得可靠的结果。
计时上下文管理器
上下文管理器提供了一种简洁的方法来计时代码块。此示例创建一个可重用的计时上下文。
import time class Timer: def __enter__(self): self.start = time.perf_counter() return self def __exit__(self, *args): self.end = time.perf_counter() self.duration = self.end - self.start print(f"Execution took {self.duration:.6f} seconds") # Using the context manager with Timer(): # Code to time data = [x**2 for x in range(10000)] filtered = [x for x in data if x % 2 == 0] total = sum(filtered) print(f"Total: {total}")
上下文管理器自动处理计时启动/停止和输出。在对多个代码部分进行计时时,此模式减少了样板代码。
持续时间在块之后仍然可以作为 timer.duration
使用。
测量小代码段
perf_counter
擅长测量非常短的操作。此示例对单个列表操作进行计时。
import time def time_operation(operation, n=1000): start = time.perf_counter() for _ in range(n): operation() end = time.perf_counter() return (end - start) / n # Define operations def list_append(): lst = [] lst.append(1) def list_concat(): lst = [] lst = lst + [1] # Time operations append_time = time_operation(list_append) concat_time = time_operation(list_concat) print(f"Append: {append_time:.9f} sec/op") print(f"Concat: {concat_time:.9f} sec/op") print(f"Ratio: {concat_time/append_time:.1f}x")
通过重复操作和求平均值,我们可以测量非常短的持续时间。 这揭示了相似操作之间的性能差异。
:.9f
格式显示这些微小持续时间的纳秒精度。
与 time.time 比较
此示例演示了短间隔内 perf_counter
和 time.time
之间的分辨率差异。
import time def empty_function(): pass # Test with time.time start = time.time() empty_function() end = time.time() print(f"time.time resolution: {end - start:.9f} sec") # Test with perf_counter start = time.perf_counter() empty_function() end = time.perf_counter() print(f"perf_counter resolution: {end - start:.9f} sec") # Measure smallest detectable difference def measure_resolution(func): min_diff = float('inf') for _ in range(100): start = func() end = func() diff = end - start if 0 < diff < min_diff: min_diff = diff return min_diff print(f"time.time min resolution: {measure_resolution(time.time):.9f}") print(f"perf_counter min resolution: {measure_resolution(time.perf_counter):.9f}")
perf_counter
通常显示比 time.time
高得多的分辨率,使其更适合微基准测试。
分辨率测试测量可检测到的最小非零计时差异。
多次运行的统计计时
对于可靠的基准测试,多次运行和统计分析有助于解决可变性。此示例显示了高级计时技术。
import time import statistics def benchmark(func, n=1000): times = [] for _ in range(n): start = time.perf_counter() func() end = time.perf_counter() times.append(end - start) mean = statistics.mean(times) stdev = statistics.stdev(times) minimum = min(times) maximum = max(times) print(f"Mean: {mean:.9f} sec") print(f"StdDev: {stdev:.9f} sec") print(f"Min: {minimum:.9f} sec") print(f"Max: {maximum:.9f} sec") print(f"Range: {maximum/minimum:.1f}x") def test_function(): sum(x*x for x in range(1000)) print("Benchmark results:") benchmark(test_function)
与单次测量相比,此方法提供了更完整的性能特征图。它有助于识别可变性和异常值。
标准偏差等统计测量显示了跨运行的计时一致性。
最佳实践
- 用于短间隔: perf_counter 是微基准测试的理想选择
- 多次运行: 多次测量以获得可靠的结果
- 预热: 考虑放弃第一次测量
- 系统负载: 在安静的系统上运行基准测试
- 相对比较: 比较实现,而不是绝对时间
资料来源
作者
列出所有 Python 教程。