Python篇---代码性能测试

一、为什么需要性能测试?

想象一下:

  • 你发明了一辆新车,不测试速度就上路 ❌

  • 你写了代码,不测试速度就上线 ❌

性能测试就是给代码"测速",找出"堵车"的地方!


二、最简单的性能测试:秒表计时法

方法1:用time模块(就像手机秒表)

import time # 记录开始时间 start_time = time.time() # 这里是你要测试的代码 total = 0 for i in range(1000000): # 循环100万次 total += i # 记录结束时间 end_time = time.time() # 计算用时 time_used = end_time - start_time print(f"代码执行耗时: {time_used:.4f} 秒") print(f"相当于: {time_used * 1000:.2f} 毫秒")

实际输出:

代码执行耗时: 0.0451 秒 相当于: 45.10 毫秒

方法2:time.perf_counter()(更精确的秒表)

import time # 这个比time.time()更精确 start = time.perf_counter() # 测试代码 numbers = [i for i in range(1000000)] end = time.perf_counter() print(f"耗时: {end - start:.6f} 秒") # 显示6位小数

方法3:timeit模块(专业计时器)

import timeit # 测试两种写法的速度 code1 = """ numbers = [] for i in range(1000): numbers.append(i) """ code2 = """ numbers = [i for i in range(1000)] """ # 每种方法运行1000次,取最快结果 time1 = timeit.timeit(code1, number=1000) time2 = timeit.timeit(code2, number=1000) print(f"传统循环: {time1:.4f} 秒") print(f"列表生成式: {time2:.4f} 秒") print(f"列表生成式快了 {(time1-time2)/time1*100:.1f}%")

三、找到代码的"堵车点":性能分析

方法1:cProfile(代码交通摄像头)

import cProfile def slow_function(): """模拟一个慢函数""" total = 0 for i in range(100000): total += i return total def fast_function(): """模拟一个快函数""" return sum(range(100000)) def main(): """主函数""" result1 = slow_function() result2 = fast_function() print(f"结果: {result1}, {result2}") # 性能分析 print("=== 开始性能分析 ===") cProfile.run('main()')

输出结果解读:

200005 function calls in 0.025 seconds # 总共调用了200005次函数,耗时0.025秒 Ordered by: standard name # 按函数名排序 ncalls tottime percall cumtime percall filename:lineno(function) # 调用次数 本函数总时间 每次调用时间 累计时间 累计每次时间 文件名:行号(函数名) 1 0.020 0.020 0.020 0.020 test.py:5(slow_function) # slow_function被调用1次,自己花了0.020秒 1 0.001 0.001 0.001 0.001 test.py:10(fast_function) # fast_function只花了0.001秒

方法2:line_profiler(逐行分析)

需要先安装:pip install line_profiler

# test_performance.py @profile # 添加这个装饰器 def process_data(): data = [] # 第1行:创建空列表 for i in range(10000): # 第2行:循环 if i % 2 == 0: # 第3行:判断是否为偶数 data.append(i * 2) # 第4行:计算并添加 return sum(data) # 第5行:求和返回 if __name__ == "__main__": process_data()

运行分析:

kernprof -l -v test_performance.py

输出结果:

Line # Hits Time Per Hit % Time Line Contents ============================================================== 1 @profile 2 def process_data(): 3 1 2.0 2.0 0.0 data = [] 4 10001 4040.0 0.4 5.8 for i in range(10000): 5 10000 4563.0 0.5 6.6 if i % 2 == 0: 6 5000 5987.0 1.2 8.7 data.append(i * 2) 7 1 54321.0 54321.0 78.9 return sum(data)

关键发现:sum(data)占了78.9%的时间!是主要瓶颈。


四、内存使用分析:你的代码"吃"多少内存?

方法1:memory_profiler(内存监测仪)

安装:pip install memory_profiler

# memory_test.py from memory_profiler import profile @profile # 内存分析装饰器 def memory_intensive(): """消耗内存的函数""" # 第1步:创建一个很大的列表 big_list = [i for i in range(100000)] # 10万个数字 print(f"列表长度: {len(big_list)}") # 第2步:创建另一个大列表 big_list2 = [str(i) for i in range(100000)] # 10万个字符串 # 第3步:删除第一个列表 del big_list return big_list2 if __name__ == "__main__": memory_intensive()

运行:

python -m memory_profiler memory_test.py

输出解读:

Line # Mem usage Increment Line Contents ================================================ 3 38.262 MiB 38.262 MiB @profile 4 def memory_intensive(): 5 41.809 MiB 3.547 MiB big_list = [i for i in range(100000)] 6 41.809 MiB 0.000 MiB print(f"列表长度: {len(big_list)}") 7 48.094 MiB 6.285 MiB big_list2 = [str(i) for i in range(100000)] 8 41.809 MiB -6.285 MiB del big_list 9 41.809 MiB 0.000 MiB return big_list2

发现:字符串列表比数字列表多占用约6.3MB内存!


方法2:sys.getsizeof()(查看对象大小)

import sys # 查看各种数据类型占多少内存 data_types = [ 100, # 整数 100.0, # 浮点数 "hello", # 短字符串 "hello" * 100, # 长字符串 [1, 2, 3], # 小列表 [i for i in range(1000)], # 大列表 ] for item in data_types: size = sys.getsizeof(item) print(f"{type(item).__name__:15} 占用 {size:6} 字节")

五、实战案例:优化一个慢程序

原始版本(慢速)

# slow_version.py import time def find_duplicates_slow(numbers): """找出列表中的重复元素(慢版本)""" duplicates = [] for i in range(len(numbers)): for j in range(i + 1, len(numbers)): if numbers[i] == numbers[j]: if numbers[i] not in duplicates: # 这里又循环一次! duplicates.append(numbers[i]) return duplicates # 测试 data = [1, 2, 3, 4, 5, 1, 2, 3, 6, 7, 8] * 1000 # 放大问题 start = time.time() result = find_duplicates_slow(data) end = time.time() print(f"找到 {len(result)} 个重复元素") print(f"耗时: {end - start:.2f} 秒")

优化版本(快速)

# fast_version.py import time from collections import Counter def find_duplicates_fast(numbers): """找出列表中的重复元素(快速版本)""" # 使用Counter统计每个元素出现的次数 counter = Counter(numbers) # 只保留出现次数>1的元素 duplicates = [num for num, count in counter.items() if count > 1] return duplicates # 同样的测试数据 data = [1, 2, 3, 4, 5, 1, 2, 3, 6, 7, 8] * 1000 start = time.time() result = find_duplicates_fast(data) end = time.time() print(f"找到 {len(result)} 个重复元素") print(f"耗时: {end - start:.2f} 秒")

对比结果:

慢版本: 12.45 秒 🐢 快版本: 0.08 秒 🚀 速度快了: 155倍!

六、性能测试工具箱总结

工具/方法用途何时使用简单程度
time.time()简单计时快速测试代码块⭐⭐⭐⭐⭐
timeit精确计时比较不同写法的速度⭐⭐⭐⭐
cProfile函数级分析找出哪个函数最慢⭐⭐⭐
line_profiler行级分析找出函数中哪一行最慢⭐⭐
memory_profiler内存分析找出内存泄漏或高消耗⭐⭐
sys.getsizeof()对象大小查看单个对象内存占用⭐⭐⭐⭐⭐

七、初学者性能优化黄金法则

法则1:避免不必要的循环

# ❌ 不好:三层循环 result = [] for i in range(100): for j in range(100): for k in range(100): result.append(i + j + k) # ✅ 好:使用列表生成式 result = [i + j + k for i in range(100) for j in range(100) for k in range(100)]

法则2:使用合适的数据结构

# ❌ 不好:用列表检查是否存在(慢) items = [1, 2, 3, 4, 5] if 5 in items: # 需要遍历整个列表 print("找到了") # ✅ 好:用集合检查是否存在(快) items_set = {1, 2, 3, 4, 5} if 5 in items_set: # 瞬间完成 print("找到了")

法则3:批量操作代替单个操作

# ❌ 不好:每次打开关闭文件 for i in range(100): with open("data.txt", "a") as f: f.write(f"行{i}\n") # ✅ 好:批量写入 lines = [f"行{i}\n" for i in range(100)] with open("data.txt", "w") as f: f.writelines(lines) # 一次写入所有行

八、简单记忆口诀

性能测试很重要,代码速度要知晓。 time计时最简单,timeit更精确。 cProfile找瓶颈,哪个函数最耗时。 line_profiler看细节,哪行代码拖后腿。 内存分析别忘记,memory_profiler帮大忙。 优化法则记心间: 循环嵌套要小心,数据结构选合适。 批量操作效率高,避免重复计算多。 测试优化再测试,代码性能节节高!

九、最后的小贴士

  1. 先让代码工作,再让代码变快- 正确性第一

  2. 优化真正的瓶颈- 不要过度优化不重要的部分

  3. 保持代码可读- 不要为了速度让代码难以理解

  4. 记录基准数据- 优化前后对比才知道效果

记住:性能优化就像减肥,需要先"称体重"(测试),找到"胖的地方"(瓶颈),然后针对性"锻炼"(优化),最后再"称体重"验证效果!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1214796.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python篇---提升Python代码性能

提升Python代码性能:从蜗牛到火箭的秘诀 一、一句话理解 提升代码性能 减少计算机的"工作量" 选择更快的"工具" 就像送外卖: ❌ 一次只送一单,来回跑10次(慢) ✅ 一次规划好路线&#xff0c…

救命神器2026最新!8款AI论文工具测评:继续教育写作全攻略

救命神器2026最新!8款AI论文工具测评:继续教育写作全攻略 2026年AI论文工具测评:为何值得一看? 随着人工智能技术的不断进步,AI论文工具已成为学术写作中不可或缺的辅助工具。对于继续教育领域的学习者和研究者来说&am…

亲测好用10个AI论文工具,本科生搞定毕业论文!

亲测好用10个AI论文工具,本科生搞定毕业论文! AI 工具如何让论文写作变得轻松 对于许多本科生来说,撰写毕业论文是一件既紧张又充满挑战的任务。尤其是在面对选题、资料收集、结构搭建和语言表达等环节时,常常会感到无从下手。而随…

技术问题记录20260125

问题1:http报文转curl 背景 处理线上问题时,偶尔是需要进行网络抓包的(如tcpdump),用wireshark分析抓包文件时,一般能看到http请求的报文。 如下面这样:有时候需要用postman这类工具来调用,进行复现,简单来说…

北京写真馆品牌排名|宝藏款真实测评北京二十四桥又登顶啦!

北京写真馆品牌排名|宝藏款真实测评北京二十四桥又登顶啦!在北京这座古都,除了热门的网红写真机构,其实还藏着不少专注品质、风格独特的小众古风写真馆。这次我们从品牌实力、拍摄资源、技术团队、服务品质和客户口…

佐治亚理工学院团队破解AI智能体融合难题

这项由佐治亚理工学院联合达特茅斯学院和圣母大学开展的研究发表于2026年1月,论文编号为arXiv:2601.13572v1。有兴趣深入了解的读者可以通过该编号查询完整论文。 在当今人工智能的世界里,我们经常会遇到这样一个有趣的现象:有些AI智能体就像…

基于MATLAB的可见光通信(VLC)系统仿真

一、系统架构设计 1. 基本参数配置 %% 系统参数定义 params = struct(...symbol_rate, 1e6, % 符号速率 (Baud)led_bandwidth, 2e6, % LED调制带宽 (Hz)distance, 2, % 传输距离 (m)snr_range, 0:5:20, …

2026年揭秘AI搜索优化服务推荐哪家,蓝戈链企实力上榜

本榜单依托全维度市场调研与真实行业口碑,深度筛选出五家区域标杆企业,为苏州及周边中小企业选型AI搜索优化服务提供客观依据,助力精准匹配适配的服务伙伴。 TOP1 推荐:苏州蓝戈链企信息科技有限公司 推荐指数:★…

2026年性价比高的股权激励咨询品牌企业推荐,创锟咨询凸显优势

2026年企业管理数字化转型加速,股权激励已成为企业绑定核心人才、驱动战略落地、提升组织活力的关键工具。无论是上市公司的合规激励、科技创新企业的人才留存,还是传统制造企业的转型突破,专业的股权激励咨询服务直…

中鼓数据规模究竟怎么样,它在行业内影响力排行多少?

问题1:中鼓数据在市场上受欢迎吗?有具体的客户反馈或案例支撑吗? 中鼓数据在AI搜索营销赛道的受欢迎程度,其实可以从客户留存率、案例效果和市场覆盖三个维度直观体现。作为聚焦上海、苏州、嘉兴等长三角区域的AI获…

盘点2026安全帽推荐厂商,无锡华信安全设备性价比值得关注

2026年工业安全防护市场持续升级,安全帽作为头部防护的核心装备,已成为建筑、能源、化工等高危行业保障劳动者安全的第一道防线。无论是传统工业场景的基础防护需求,还是智能化作业场景的数字化监控需求,优质安全帽…

分析质量好的农业水泵哪里买,揭晓高性价比厂家

随着农业现代化、工业循环用水需求的提升,越来越多用户开始关注质量好的水泵在厂家直销处哪里买、质量好的农业水泵哪里买、质量好的循环水泵哪里买这类问题。毕竟水泵作为流体输送的核心设备,其质量直接关系到生产效…

2026年电镀金加工服务商厂家排名,哪些品牌更靠谱?

本榜单依托全维度市场调研与真实行业口碑,深度筛选出五家标杆企业,为精密零部件、金属带材制造企业选型提供客观依据,助力精准匹配适配的电镀金加工服务伙伴。 TOP1 推荐:无锡鼎亚电子材料有限公司 推荐指数:★★…

SCB 10X推出Typhoon OCR:让泰文文档识别变得轻松简单

当你拿到一份泰文政府表格或者银行对账单时,想要将里面的文字提取出来编辑,你会怎么办?如果你不懂泰语,这个任务就像在解密一样困难。传统的文字识别工具在处理英文时表现不错,但面对泰文这样复杂的文字系统时&#xf…

弗吉尼亚大学等机构突破:AI医生实现十三种语言个性化诊疗

这项由弗吉尼亚大学联合印度理工学院巴特那分校、阿联酋穆罕默德本扎耶德人工智能大学等多所知名院校共同完成的研究发表于2025年1月19日,论文编号为arXiv:2601.13262v1。对这个研究领域感兴趣的读者可以通过该编号查询完整论文。 当医生面对不同国家的病人时&#…

哥本哈根大学新发现:AI事实核查中,证据比解释更重要

这项由丹麦哥本哈根大学计算机科学系与瑞典林雪平大学合作完成的研究发表于2025年,论文编号为arXiv:2601.11387v1,为我们揭示了在AI辅助事实核查过程中,人们究竟如何使用和评估AI系统提供的信息。在当今信息爆炸的时代,人们越来越…

Roots.ai团队推出GutenOCR:让AI既能读字又能精准定位

这项由Roots.ai团队开展的研究发表于2026年1月的arXiv预印本服务器,论文编号为arXiv:2601.14490v1。有兴趣深入了解技术细节的读者可以通过该编号查询完整论文。 当你用手机扫描一份文件时,是否曾经遇到过这样的困扰:软件能够识别出文字内容&…

深入解析:开源鸿蒙-基于Flutter搭建GitCode口袋工具-2

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

物联网项目tp5怎么也获取不到请求的参数问题

做一个物联网项目时,thinkPHP5.0用常规的框架方法获取不到设备请求过来的参数,总是空。 最后用 原生PHP获取请求体 的方法得到了参数,也就是用PHP原生的方法获取参数,获取后为字符串,再转换为对象就可以用了 $raw fil…

D8 24. 两两交换链表中的节点

24 两两交换链表中的节点(力扣:https://leetcode.cn/problems/swap-nodes-in-pairs/ 条件:成对交换链表节点(而不是其中的值)剩余单数或null时退出,最后返回新head(空/单节点链表返回原head) Tips:由于可交换…