Python 性能分析与优化

2 min入门

Python 性能分析与优化 的完整教学讲解。

timeit 计时

基本写法:timeit 计时 timeit.timeit(<代码>, number=<次数>)

# 测量代码执行时间
import timeit

t = timeit.timeit("sum(range(100))", number=10000)
print(t)

基本写法:repeat 重复测量 timeit.repeat(<代码>, repeat=<次数>, number=<次数>)

# 多次重复测量
times = timeit.repeat("sum(range(100))", repeat=5, number=10000)
print(min(times))

基本写法:命令行 python -m timeit -s <setup> <代码>

# 命令行计时
# python -m timeit -s "import json" "json.dumps({'a':1})"

基本写法:Timer 对象 timeit.Timer(<代码>, setup=<准备>)

# Timer 对象
t = timeit.Timer("x.append(1)", setup="x = []")
print(t.timeit(number=100000))

time 性能计数器

基本写法:perf_counter 高精度 time.perf_counter()

# 高精度计时器
import time

start = time.perf_counter()
# 执行代码
time.sleep(0.1)
end = time.perf_counter()
print(f"耗时 {end - start:.4f}s")

基本写法:perf_counter_ns 纳秒 time.perf_counter_ns()

# 纳秒级精度
start = time.perf_counter_ns()
# 执行代码
end = time.perf_counter_ns()
print(f"耗时 {end - start}ns")

基本写法:process_time 进程时间 time.process_time()

# 进程 CPU 时间(不含睡眠)
start = time.process_time()
# 执行代码
end = time.process_time()
print(f"CPU 时间 {end - start}s")

cProfile 性能分析

基本写法:cProfile 运行 cProfile.run(<代码字符串>)

# 分析代码性能
import cProfile

cProfile.run("sum(range(1000000))")

基本写法:Profile 对象 cProfile.Profile()

# Profile 对象精细控制
prof = cProfile.Profile()
prof.enable()
# 执行代码
sum(range(100000))
prof.disable()
prof.print_stats(sort="cumtime")

基本写法:排序输出 prof.print_stats(sort=<排序>)

# 按累计时间排序
prof.print_stats(sort="cumulative")
prof.print_stats(sort="tottime")  # 按总时间

基本写法:保存到文件 prof.dump_stats(<文件>)

# 保存分析数据
prof.dump_stats("profile.prof")

基本写法:pstats 分析 pstats.Stats(<文件>)

# 加载并分析 profile 文件
import pstats

stats = pstats.Stats("profile.prof")
stats.sort_stats("cumulative").print_stats(10)

memory_profiler 内存分析

基本写法:profile 装饰器 @profile

# 需要安装 memory_profiler
# pip install memory_profiler
@profile
def my_func():
    a = [1] * 1000000
    return sum(a)

my_func()
# 运行:python -m memory_profiler script.py

基本写法:memit 内存峰值 %memit <表达式>

# IPython 中测量内存峰值
# %memit sum(range(1000000))

sys.getsizeof 内存占用

基本写法:获取对象大小 sys.getsizeof(<对象>)

# 获取对象字节大小
import sys

print(sys.getsizeof([1, 2, 3]))
print(sys.getsizeof("hello"))
print(sys.getsizeof({}))

基本写法:tracemalloc 跟踪分配 tracemalloc.start()

# 跟踪内存分配
import tracemalloc

tracemalloc.start()
# 执行代码
data = [i for i in range(100000)]
snapshot = tracemalloc.take_snapshot()
for stat in snapshot.statistics("lineno")[:5]:
    print(stat)

基本写法:比较快照 snapshot2.compare_to(snapshot1, "lineno")

# 比较两个内存快照
snap1 = tracemalloc.take_snapshot()
# 执行代码
snap2 = tracemalloc.take_snapshot()
for stat in snap2.compare_to(snap1, "lineno")[:5]:
    print(stat)

dis 字节码分析

基本写法:反汇编 dis.dis(<函数>)

# 查看函数字节码
import dis

def loop():
    total = 0
    for i in range(100):
        total += i
    return total

dis.dis(loop)

优化技巧

基本写法:列表推导优于循环 [<表达式> for <变量> in <可迭代>]

# 列表推导比 append 循环快
squares = [x * x for x in range(1000)]

基本写法:生成器节省内存 (<表达式> for <变量> in <可迭代>)

# 大数据用生成器
squares_gen = (x * x for x in range(1000000))

基本写法:set 成员查找 <值> in <集合>

# set 查找 O(1),list 查找 O(n)
valid = {"a", "b", "c"}  # 用 set 而非 list
if x in valid:
    pass

基本写法:局部变量优化 def <函数>():\n <局部变量>

# 局部变量比全局变量快
def compute():
    # 局部变量访问快
    total = sum
    return total(range(100))

基本写法:slots 节省内存 class <类>:\n __slots__ = (<字段>,)

# __slots__ 减少内存与加速属性访问
class Point:
    __slots__ = ("x", "y")
    def __init__(self, x, y):
        self.x = x
        self.y = y

基本写法:lru_cache 缓存 @functools.lru_cache(maxsize=<大小>)

# 缓存函数结果
from functools import lru_cache

@lru_cache(maxsize=128)
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

sys.monitoring 监控(3.12+)

基本写法:注册监控工具 sys.monitoring.use_tool_id(<ID>, <名称>)

# Python 3.12 低开销监控(PEP 669)
import sys.monitoring

sys.monitoring.use_tool_id(0, "my_profiler")
sys.monitoring.register_callback(
    sys.monitoring.events.PY_START,
    0,
    lambda code, offset: print("开始", code.co_name)
)

基本写法:获取事件 sys.monitoring.events

# 监控事件类型
print(sys.monitoring.events.PY_START)
print(sys.monitoring.events.PY_RESUME)
print(sys.monitoring.events.CALL)

并行加速

基本写法:多进程 CPU 密集 concurrent.futures.ProcessPoolExecutor()

# CPU 密集型用多进程
from concurrent.futures import ProcessPoolExecutor

def heavy(n):
    return sum(i * i for i in range(n))

if __name__ == "__main__":
    with ProcessPoolExecutor() as ex:
        results = list(ex.map(heavy, [1000000, 2000000, 3000000]))

基本写法:多线程 IO 密集 concurrent.futures.ThreadPoolExecutor()

# IO 密集型用多线程或 asyncio
from concurrent.futures import ThreadPoolExecutor
import urllib.request

def fetch(url):
    with urllib.request.urlopen(url) as r:
        return r.read()

with ThreadPoolExecutor(max_workers=10) as ex:
    results = list(ex.map(fetch, urls))

字符串拼接优化

基本写法:join 优于 + "<分隔>".join(<字符串列表>)

# join 比 + 拼接高效
parts = ["a", "b", "c"]
result = "".join(parts)  # 优于 result = parts[0] + parts[1] + ...