Python time.monotonic_ns 函数
上次修改时间:2025 年 4 月 11 日
本综合指南探讨了 Python 的 time.monotonic_ns
函数,该函数返回一个纳秒级分辨率的单调时钟值。我们将介绍精确计时、性能测量和实际示例。
基本定义
time.monotonic_ns
函数以纳秒为单位返回一个时钟值。它是单调的(永不减少)并且不受系统时钟调整的影响。
主要特点:纳秒级分辨率,非常适合精确的计时间隔,并保证永远不会倒退。参考点未定义,但在程序执行期间是一致的。
monotonic_ns 的基本用法
此示例演示了 time.monotonic_ns
的基本用法,用于测量具有纳秒精度的计时间隔。
import time # Get current monotonic time in nanoseconds start = time.monotonic_ns() # Simulate some work time.sleep(0.5) # Sleep for 500 milliseconds # Get end time end = time.monotonic_ns() # Calculate duration in nanoseconds duration_ns = end - start duration_ms = duration_ns / 1_000_000 # Convert to milliseconds print(f"Operation took {duration_ns} nanoseconds") print(f"Which is {duration_ms:.2f} milliseconds")
此示例展示了如何以纳秒精度测量时间间隔。即使系统时钟发生变化,睡眠持续时间也能被准确测量。
请注意,虽然分辨率为纳秒,但实际精度取决于底层系统能力。
比较 monotonic_ns 和 monotonic
此示例将 time.monotonic_ns
与 time.monotonic
进行比较,以显示精度和表示形式的差异。
import time def test_function(): sum(range(1_000_000)) # Using time.monotonic() start = time.monotonic() test_function() end = time.monotonic() print(f"time.monotonic(): {(end - start) * 1e9:.0f} ns") # Using time.monotonic_ns() start = time.monotonic_ns() test_function() end = time.monotonic_ns() print(f"time.monotonic_ns(): {end - start} ns")
这两个函数使用相同的底层时钟,但 monotonic_ns
提供对纳秒值的直接访问,无需浮点转换。
对于非常精确的测量,monotonic_ns
版本避免了潜在的浮点精度问题。
使用 monotonic_ns 进行微基准测试
此示例演示了如何使用 time.monotonic_ns
对具有高精度的小代码段进行微基准测试。
import time def benchmark(func, iterations=1_000_000): start = time.monotonic_ns() for _ in range(iterations): func() end = time.monotonic_ns() ns_per_op = (end - start) / iterations print(f"{func.__name__}: {ns_per_op:.2f} ns/operation") def empty_function(): pass def simple_math(): 42 * 42 benchmark(empty_function) benchmark(simple_math)
此模式对于测量非常小的操作的性能非常有用。纳秒分辨率允许对单个操作进行精确计时。
请注意,微基准测试可能会受到各种系统因素的影响,应谨慎解释。
精确的速率限制
此示例使用 time.monotonic_ns
实现了一个高精度速率限制器,以纳秒级的精度控制操作频率。
import time class NanoRateLimiter: def __init__(self, operations_per_second): self.interval_ns = 1_000_000_000 // operations_per_second self.last_run = 0 def __call__(self, func): def wrapper(*args, **kwargs): now = time.monotonic_ns() elapsed = now - self.last_run if elapsed < self.interval_ns: delay_ns = self.interval_ns - elapsed time.sleep(delay_ns / 1e9) # Convert to seconds self.last_run = time.monotonic_ns() return func(*args, **kwargs) return wrapper @NanoRateLimiter(1000) # 1000 operations per second def high_freq_operation(): print("Operation at", time.monotonic_ns() % 1_000_000) for _ in range(5): high_freq_operation()
速率限制器通过精确测量纳秒级的时间间隔,确保操作不会超过指定的速率。
这对于硬件控制或高频 API 尤其有用,在这些情况下,精确计时至关重要。
测量小代码块
此示例展示了如何使用 time.monotonic_ns
和上下文管理器来方便地测量非常小的代码块。
import time from contextlib import contextmanager @contextmanager def time_ns(): start = time.monotonic_ns() yield end = time.monotonic_ns() print(f"Duration: {end - start} ns") # Measure list comprehension with time_ns(): squares = [x*x for x in range(1000)] # Measure dictionary creation with time_ns(): d = {x: x*x for x in range(1000)}
上下文管理器自动测量并打印 with
语句中代码块的执行时间。
这种模式可以很容易地将精确计时添加到现有代码中,而不会用计时代码使逻辑混乱。
长时间运行的进程监控
此示例演示了如何使用 time.monotonic_ns
来监控长时间运行的进程,并定期更新进度。
import time def long_running_task(): total_items = 1_000_000 start_time = time.monotonic_ns() last_report = start_time for i in range(total_items): # Simulate work time.sleep(0.001) # Report progress every second current_time = time.monotonic_ns() if current_time - last_report >= 1_000_000_000: elapsed_s = (current_time - start_time) / 1_000_000_000 progress = (i + 1) / total_items * 100 print(f"{elapsed_s:.1f}s: {progress:.1f}% complete") last_report = current_time total_time = (time.monotonic_ns() - start_time) / 1_000_000_000 print(f"Task completed in {total_time:.2f} seconds") long_running_task()
该示例使用纳秒级计时来精确控制进度报告的时间间隔,同时避免浮点累积误差造成的漂移。
这种方法确保即使对于非常长时间运行的进程,计时也是准确的,因为很小的计时误差可能会累积得非常显著。
最佳实践
- 精度需求: 当需要纳秒分辨率时,使用 monotonic_ns
- 长时间持续: 请注意长时间测量可能导致整数溢出
- 系统限制: 实际精度取决于操作系统和硬件
- 时钟源: 使用系统上可用的最佳单调时钟
- 转换: 需要时,除以 1e9 得到秒数
资料来源
作者
列出所有 Python 教程。