首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python性能分析 | 性能瓶颈定位 | 优化方案实施

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和内存分析

掌握这些招数,基本能应付大部分性能优化需求了。当然,具体问题具体分析,没有银弹。性能优化是个迭代的过程,需要不断测试和改进。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OLJPnZS7pWEF55AMu48hBnhw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券