您的位置:

如何使用Python time perf_counter方法测量代码性能

一、time模块的使用

在Python中,可以使用time模块来测量代码的性能。具体来说,我们可以使用time.perf_counter()函数来计算程序运行时间。


import time

start_time = time.perf_counter()

# 待测试的代码

end_time = time.perf_counter()

print("程序运行时间:", end_time - start_time)

time.perf_counter()函数返回的是CPU执行时间,单位是秒。我们分别在代码开始和结束位置取得时间,并计算时间差,就能得出程序的运行时间。

二、使用timeit模块进行多次测量

如果我们想测试代码的性能稳定性,可以多次运行代码并取平均值。Python中有一个timeit模块,它可以方便地进行多次性能测试。


import timeit

t = timeit.Timer("待测试的代码", "import 模块")

print("程序运行时间:", t.timeit(number=1000)) # 进行1000次测试,并计算平均值

timeit.Timer()函数可以传入两个参数,第一个参数是待测试的代码,第二个参数是需要导入的模块。我们可以通过设置number参数来指定测试次数。timeit.Timer.timeit()方法会返回经过多次测试后的平均运行时间。

三、性能优化

测量完程序的性能后,我们可以对程序进行优化,以提高程序的运行速度。

最普遍的性能优化方式之一就是减少循环次数。如果存在多层循环,可以将内层循环尽可能提到外层循环外面来减少循环次数。同时,也可以考虑使用一些新的数据结构来替换原有的算法。

四、实例:计算斐波那契数列

我们以计算斐波那契数列为例来测试代码性能,并进行优化。

斐波那契数列是一个非常经典的数列,下一项的值是前两项的和,即:0, 1, 1, 2, 3, 5, 8, 13, 21……

首先,我们看一下最基础的计算斐波那契数列的代码:


def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(30))

这段代码的时间复杂度是O(2^n),n越大,计算时间越长。

接下来,我们进行优化。首先,我们将已经计算过的值保存下来,避免重复计算。这样做可以大大减少循环次数。


memo = {} # 存储已经计算过的值

def fibonacci(n):
    if n <= 1:
        return n
    if n not in memo:
        memo[n] = fibonacci(n-1) + fibonacci(n-2)
    return memo[n]

print(fibonacci(30))

下一步,我们考虑循环计算斐波那契数列。在循环中,我们只需存储前两个数值并依次更新,就能计算出所有的斐波那契数列。


def fibonacci(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

print(fibonacci(30))

最后,我们通过time模块来测试不同算法的性能,并对比不同算法的运行时间。


import time

def fibonacci_recursive(n):
    if n <= 1:
        return n
    else:
        return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)

def fibonacci_memo(n, memo):
    if n <= 1:
        return n
    if n not in memo:
        memo[n] = fibonacci_memo(n-1, memo) + fibonacci_memo(n-2, memo)
    return memo[n]

def fibonacci_loop(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

start_time = time.perf_counter()
print(fibonacci_recursive(35))
end_time = time.perf_counter()
print("递归算法的运行时间:", end_time - start_time)

start_time = time.perf_counter()
print(fibonacci_memo(35, {}))
end_time = time.perf_counter()
print("使用备忘录的递归算法的运行时间:", end_time - start_time)

start_time = time.perf_counter()
print(fibonacci_loop(100000))
end_time = time.perf_counter()
print("循环算法的运行时间:", end_time - start_time)

运行结果表明,递归算法的运行时间最长,循环算法的运行时间最短。使用备忘录的递归算法与循环算法的运行时间差距不大。