Python性能分析与优化实战指南
最近帮一个团队优化了他们的Python项目,性能提升了3倍多。这里把经验和套路分享给大家,希望对你们有帮助。
定位性能瓶颈
要优化性能,得先找到瓶颈在哪。我常用的方案是用cProfile和line_profiler这两个工具。cProfile可以看到函数级别的耗时,line_profiler能定位到具体代码行。
来看个具体例子:
import cProfileimport timedefslow_function(): time.sleep(1) result = []for iinrange(100000): result.append(i **2)return resultdefmain():for _inrange(3): slow_function()# 使用cProfile分析cProfile.run('main()')
运行后会输出每个函数的调用次数和耗时。看到slow_function很慢,我们用line_profiler进一步定位:
@profiledefslow_function(): time.sleep(1) result = []for iinrange(100000): result.append(i **2)return result
运行kernprof -l -v script.py,就能看到每行代码的执行时间。
常见性能陷阱与优化方案
列表操作是个大坑。看这段代码:
# 低效的写法numbers = []for iinrange(1000000): numbers.append(i)# 高效写法numbers =list(range(1000000))
列表推导式通常比循环append快很多。再来看字符串拼接:
# 低效写法s =''for iinrange(1000): s +=str(i)# 高效写法s =''.join(str(i)for iinrange(1000))
用join比+拼接字符串快得多,因为字符串是不可变对象。
内存优化tricks
处理大数据时,内存往往是瓶颈。生成器表达式就很给力:
# 内存占用大numbers = [i * ifor iinrange(10000000)]# 内存友好numbers = (i * ifor iinrange(10000000))
生成器按需生成数据,不会一次性占用太多内存。处理大文件也可以用这招:
# 可能爆内存withopen('big_file.txt')as f: content = f.read()# 内存友好withopen('big_file.txt')as f:for linein f: process(line)
多进程加速
CPU密集型任务,用多进程可以充分利用多核性能:
from multiprocessingimport Pooldefheavy_computation(x):return x * xif __name__ =='__main__': numbers =range(10000000)# 单进程 results = [heavy_computation(x)for xin numbers]# 多进程with Pool()as p: results = p.map(heavy_computation, numbers)
注意要把进程数设置得和CPU核心数相匹配。
使用性能更好的数据结构
选对数据结构很关键:
# 低效found =Falsefor itemin big_list:if item == target: found =Truebreak# 高效found = targetinset(big_list)
set的查找是O(1),而list是O(n)。同理,dict的get比list的index快得多。
代码优化案例
把上面说的都整合起来,优化一个实际的例子:
# 优化前defprocess_data(filename): results = []withopen(filename)as f: data = f.readlines()for linein data: num =int(line.strip()) results.append(num * num) total =0for rin results: total += rreturn total# 优化后from itertoolsimport islicedefprocess_data(filename):withopen(filename)as f:returnsum(int(line.strip())**2for linein f)
优化后的代码更简洁,性能更好,内存占用也更少。
性能优化建议
先分析再优化,避免过早优化
注意选择合适的数据结构
多用内置函数和标准库
生成器节省内存
CPU密集用多进程,IO密集用异步
代码简洁通常性能也不会差
工具推荐
cProfile: 函数级性能分析
line_profiler: 代码行级性能分析
memory_profiler: 内存分析
py-spy: 实时性能监控
scalene: CPU和内存分析
掌握这些招数,基本能应付大部分性能优化需求了。当然,具体问题具体分析,没有银弹。性能优化是个迭代的过程,需要不断测试和改进。
领取专属 10元无门槛券
私享最新 技术干货