ZetCode

Python time.process_time_ns 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨了 Python 的 time.process_time_ns 函数,该函数以纳秒为单位返回进程时间。我们将介绍高精度计时、性能测量和实际示例。

基本定义

time.process_time_ns 函数以纳秒为单位返回当前进程时间作为整数。进程时间测量进程使用的 CPU 时间。

主要特性:纳秒精度,测量 CPU 时间(不是挂钟时间),并排除睡眠时间。它非常适合对 CPU 密集型操作进行基准测试。返回值是一个整数,用于精确的计时测量。

基本进程时间测量

time.process_time_ns 最简单的用法是测量进程时间。 此示例显示了基本用法和转换为秒。

basic_process_time.py
import time

# Get current process time in nanoseconds
process_time_ns = time.process_time_ns()
print(f"Process time: {process_time_ns} ns")

# Convert to seconds
process_time_sec = process_time_ns / 1e9
print(f"Process time: {process_time_sec:.9f} seconds")

此示例演示如何获取当前进程时间(以纳秒为单位)。 该值将转换为秒,以便于人工阅读。

请注意,与挂钟时间不同,进程时间仅在 CPU 积极处理您的进程时才会增加。

测量函数执行时间

time.process_time_ns 非常适合测量函数的 CPU 时间。 此示例显示了如何计时 CPU 密集型操作。

function_timing.py
import time

def calculate_primes(n):
    primes = []
    for candidate in range(2, n + 1):
        is_prime = True
        for divisor in range(2, int(candidate ** 0.5) + 1):
            if candidate % divisor == 0:
                is_prime = False
                break
        if is_prime:
            primes.append(candidate)
    return primes

# Start timer
start_time = time.process_time_ns()

# Execute CPU-bound function
primes = calculate_primes(10000)

# Calculate duration
end_time = time.process_time_ns()
duration_ns = end_time - start_time

print(f"Found {len(primes)} primes in {duration_ns / 1e6:.3f} ms")

此模式仅测量计算使用的 CPU 时间,排除任何等待或睡眠时间。 结果以纳秒为单位。

持续时间转换为毫秒以提高可读性,同时保持精度。

比较进程时间和挂钟时间

此示例比较进程时间和挂钟时间,以显示包括睡眠操作时的差异。

compare_times.py
import time

def mixed_operation():
    # CPU-bound work
    sum(range(1000000))
    # I/O-bound wait
    time.sleep(1)
    # More CPU work
    sum(range(2000000))

# Wall-clock time measurement
wall_start = time.time()
mixed_operation()
wall_end = time.time()
print(f"Wall time: {(wall_end - wall_start) * 1e3:.3f} ms")

# Process time measurement
proc_start = time.process_time_ns()
mixed_operation()
proc_end = time.process_time_ns()
print(f"Process time: {(proc_end - proc_start) / 1e6:.3f} ms")

挂钟时间包括睡眠时间,而进程时间仅计算活跃 CPU 使用率。 这说明了它们在具有等待时间的操作中的不同之处。

进程时间更适合测量实际 CPU 工作负载,而挂钟时间测量总经过时间。

使用 process_time_ns 进行微基准测试

对于微基准测试,process_time_ns 提供纳秒精度。 此示例多次对小操作进行基准测试。

microbenchmark.py
import time

def benchmark(func, iterations=1000000):
    start = time.process_time_ns()
    for _ in range(iterations):
        func()
    end = time.process_time_ns()
    ns_per_op = (end - start) / iterations
    print(f"{func.__name__}: {ns_per_op:.2f} ns/operation")

def empty_func():
    pass

def small_calc():
    3.14159 * 2.71828

benchmark(empty_func)
benchmark(small_calc)

这通过运行多次迭代并划分总时间来测量每次操作的成本。 纳秒精度揭示了细微的性能差异。

请注意,现代 CPU 可能会优化空循环,因此应谨慎解释结果。

分析代码段

process_time_ns 可以单独分析不同的代码段。 此示例显示了详细的 CPU 时间细分。

profiling.py
import time

def complex_operation():
    # Section 1: Setup
    start1 = time.process_time_ns()
    data = [i**2 for i in range(10000)]
    end1 = time.process_time_ns()
    
    # Section 2: Processing
    start2 = time.process_time_ns()
    result = sum(x % 7 for x in data)
    end2 = time.process_time_ns()
    
    # Section 3: Cleanup
    start3 = time.process_time_ns()
    sorted_data = sorted(data)
    end3 = time.process_time_ns()
    
    # Report timings
    print(f"Setup: {(end1 - start1) / 1e6:.3f} ms")
    print(f"Processing: {(end2 - start2) / 1e6:.3f} ms")
    print(f"Cleanup: {(end3 - start3) / 1e6:.3f} ms")
    return result

complex_operation()

此模式有助于识别函数的哪些部分消耗最多的 CPU 时间。 每个部分都独立计时,以进行详细分析。

结果转换为毫秒以提高可读性,同时保持对每个部分的精确测量。

比较算法

此示例使用 process_time_ns 来比较解决相同问题的不同算法的性能。

algorithm_comparison.py
import time

def factorial_recursive(n):
    return 1 if n <= 1 else n * factorial_recursive(n - 1)

def factorial_iterative(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result

def time_algorithm(func, arg):
    start = time.process_time_ns()
    result = func(arg)
    end = time.process_time_ns()
    return result, end - start

n = 500
result_rec, time_rec = time_algorithm(factorial_recursive, n)
result_it, time_it = time_algorithm(factorial_iterative, n)

print(f"Recursive: {time_rec / 1e6:.3f} ms")
print(f"Iterative: {time_it / 1e6:.3f} ms")
print(f"Same result: {result_rec == result_it}")

该示例比较了递归和迭代阶乘实现。 进程时间测量显示哪种方法的 CPU 效率更高。

请注意,对于非常大的 n,递归版本可能会在显示其完整性能特征之前达到 Python 的递归限制。

跟踪累积进程时间

此示例演示了如何使用 process_time_ns 跟踪多个操作中的累积 CPU 时间。

cumulative_time.py
import time
import random

def perform_work():
    # Simulate variable CPU workload
    n = random.randint(100000, 500000)
    sum(range(n))

total_cpu_ns = 0
operations = 0

while total_cpu_ns < 5e9:  # Run until 5 seconds CPU time
    start = time.process_time_ns()
    perform_work()
    end = time.process_time_ns()
    
    operation_time = end - start
    total_cpu_ns += operation_time
    operations += 1
    
    print(f"Op {operations}: {operation_time / 1e6:.3f} ms", end=" | ")
    print(f"Total: {total_cpu_ns / 1e9:.3f} s")

print(f"\nCompleted {operations} operations in {total_cpu_ns / 1e9:.3f} s CPU time")

这会跟踪一系列操作消耗的总 CPU 时间,直到达到阈值。 每次操作的贡献都经过精确测量。

该示例显示了如何监视批量处理或长时间运行的任务的累积 CPU 使用率。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程