Python代码性能优化基础
1.1 Python性能瓶颈全景图
1.1.1 性能瓶颈分类
┌───────────────┐
│ 性能瓶颈类型 │
└──────┬────────┘
│
┌───────┬─────┴───┬───────┐
▼ ▼ ▼ ▼
┌─────────┐┌───────┐┌────────┐┌───────┐
│ CPU计算 ││ 内存 ││ I/O操作 ││ 并发 │
└─────────┘└───────┘└────────┘└───────┘
典型场景诊断表
症状 | 可能原因 | 推荐工具 |
CPU持续满载 | 算法复杂度高 | cProfile、py-spy |
内存占用持续增长 | 内存泄漏/数据冗余 | tracemalloc、objgraph |
程序间歇性卡顿 | GIL争用/锁冲突 | py-spy、threading模块 |
磁盘/网络I/O延迟高 | 同步阻塞调用 | strace、aiohttp监控 |
1.2 性能分析工具链
1.2.1 时间性能分析
cProfile基础用法
# 生成性能分析报告
python -m cProfile -o output.prof my_script.py
# 查看耗时Top10函数
python -c "import pstats; p = pstats.Stats('output.prof'); p.sort_stats('cumulative').print_stats(10)"
可视化分析(snakeviz)
pip install snakeviz
snakeviz output.prof # 生成火焰图
1.2.2 内存分析
对象级内存追踪
import tracemalloc
tracemalloc.start()
# 执行待测代码
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
print("[ Top 10 memory allocations ]")
for stat in top_stats[:10]:
print(stat)
实时内存监控(memory-profiler)
# 安装:pip install memory-profiler
from memory_profiler import profile
@profile(precision=4)
def process_data():
data = [i**2 for i in range(100000)]
return sum(data)
if __name__ == '__main__':
process_data()
输出示例:
Line # Mem usage Increment Occurences Line Contents
============================================================
3 38.2344 MiB 38.2344 MiB 1 def process_data():
4 41.7852 MiB 3.5508 MiB 1 data = [i**2 for i in range(100000)]
5 41.7852 MiB 0.0000 MiB 1 return sum(data)
1.2.3 行级性能分析
line-profiler实战
# 安装:pip install line-profiler
# kernprof.py -l -v script.py
def primes(n):
primes = []
for num in range(2, n):
if all(num % i != 0 for i in range(2, int(num**0.5)+1)):
primes.append(num)
return primes
primes(1000) # 测试执行
分析结果:
Total time: 0.123456 s
File: primes.py
Function: primes at line 1
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1 def primes(n):
2 1 2.0 2.0 0.0 primes = []
3 999 345.0 0.3 0.3 for num in range(2, n):
4 998 123456.0 123.7 99.6 if all(num % i != 0 for i in range(2, int(num**0.5)+1)):
5 143 56.0 0.4 0.1 primes.append(num)
6 1 1.0 1.0 0.0 return primes
1.3 复杂度分析与Big-O速查表
1.3.1 常见时间复杂度曲线
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1, 20, 100)
plt.plot(x, np.log(x), label='O(log n)')
plt.plot(x, x, label='O(n)')
plt.plot(x, x*np.log(x), label='O(n log n)')
plt.plot(x, x**2, label='O(n^2)')
plt.legend()
plt.title('常见时间复杂度增长曲线')
plt.show()
1.3.2 数据结构操作复杂度速查
数据结构 | 访问 | 搜索 | 插入 | 删除 | 空间复杂度 |
列表(list) | O(1) | O(n) | O(n) | O(n) | O(n) |
集合(set) | - | O(1) | O(1) | O(1) | O(n) |
字典(dict) | O(1) | O(1) | O(1) | O(1) | O(n) |
双向队列(deque) | O(1) | O(n) | O(1) | O(1) | O(n) |
1.3.3 算法优化案例
问题:查找列表中出现次数最多的元素
初始实现(O(n^2)):
def find_most_frequent(lst):
max_count = 0
most_common = None
for item in lst:
count = lst.count(item)
if count > max_count:
max_count = count
most_common = item
return most_common
优化实现(O(n)):
from collections import defaultdict
def optimized_find_most_frequent(lst):
counter = defaultdict(int)
for item in lst:
counter[item] += 1
return max(counter, key=counter.get)
性能对比:
import timeit
data = [i%100 for i in range(10000)]
t1 = timeit.timeit('find_most_frequent(data)',
setup='from __main__ import find_most_frequent, data',
number=100)
t2 = timeit.timeit('optimized_find_most_frequent(data)',
setup='from __main__ import optimized_find_most_frequent, data',
number=100)
print(f"原始版本耗时:{t1:.4f}s")
print(f"优化版本耗时:{t2:.4f}s")
# 输出示例:原始版本耗时:3.2145s → 优化版本耗时:0.0123s
小结
性能优化三步法
- 定位瓶颈:使用cProfile/memory-profiler确定主消耗源
- 复杂度评估:通过Big-O分析选择更优算法
- 工具验证:用timeit对比优化前后效果
推荐学习路径
- 完成本章所有代码实操
- 对现有项目进行性能分析
- 尝试优化一个已知性能问题的函数
将陆续更新 Python 编程相关的学习资料!
作者:ICodeWR
标签:#编程# #春日生活打卡季# #在头条记录我的2025# #python#