cProfile-执行时间、频率分析

描述程序的各个部分执行的频率和时间

https://docs.python.org/zh-cn/3/library/profile.html https://www.cnblogs.com/btchenguang/archive/2012/02/03/2337112.html https://blog.csdn.net/asukasmallriver/article/details/74356771 https://blog.csdn.net/cxu0262/article/details/107264113

  1. a_list = []
  2. def a():
  3. for i in range(5000):
  4. a_list.append(i)
  5. return a_list
  6. a = a()
  7. # print(a)
  8. # 直接把分析结果打印到控制台
  9. # python3 -m cProfile /home/work/baidu/personal-code/wanshunzhe-script/wanshunzhe_script/tests/base/test_profile.py
  10. # 把分析结果保存到文件中
  11. # python3 -m cProfile -o result.out /home/work/baidu/personal-code/wanshunzhe-script/wanshunzhe_script/tests/base/test_profile.py
  12. # 增加排序方式
  13. # python3 -m cProfile -o result.out -s cumulative test.py
  1. """因为文件是以二进制保存的,打开时显示乱码,可通过pstats模块,用来分析cProfile输出的文件内容"""
  2. import pstats
  3. # 创建Stats对象
  4. p = pstats.Stats("result.out")
  5. # strip_dirs(): 去掉无关的路径信息
  6. # sort_stats(): 排序,支持的方式和上述的一致
  7. # print_stats(): 打印分析结果,可以指定打印前几行
  8. # 和直接运行cProfile.run("test()")的结果是一样的
  9. p.strip_dirs().sort_stats(-1).print_stats()
  10. # 按照函数名排序,只打印前3行函数的信息, 参数还可为小数,表示前百分之几的函数信息
  11. p.strip_dirs().sort_stats("name").print_stats(3)
  12. # 按照运行时间和函数名进行排序
  13. p.strip_dirs().sort_stats("cumulative", "name").print_stats(0.5)
  14. # 如果想知道有哪些函数调用了sum_num
  15. # p.print_callers(0.5, "sum_num")
  16. # 查看test()函数中调用了哪些函数
  17. # p.print_callees("test")
  18. # ncalls:表示函数调用的次数;
  19. # tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
  20. # percall:(第一个percall)等于 tottime/ncalls;
  21. # cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
  22. # percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
  23. # filename:lineno(function):每个函数调用的具体信息;
  24. """
  25. Tue Jun 28 23:57:00 2022 result.out
  26. 5004 function calls in 0.002 seconds
  27. Ordered by: standard name
  28. ncalls tottime percall cumtime percall filename:lineno(function)
  29. 1 0.001 0.001 0.002 0.002 test_profile.py:10(a)
  30. 1 0.000 0.000 0.002 0.002 test_profile.py:8(<module>)
  31. 1 0.000 0.000 0.002 0.002 {built-in method builtins.exec}
  32. 5000 0.001 0.000 0.001 0.000 {method 'append' of 'list' objects}
  33. 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
  34. """

tracemalloc-跟踪内存分配

跟踪python分配的内存块

https://www.osgeo.cn/cpython/library/tracemalloc.html

显示分配最多内存的10个文件

  1. import tracemalloc
  2. # 开始跟踪内存分配,默认情况下,分配内存块的跟踪只存储最新的帧(1帧)。可设置在启动时存储25帧
  3. tracemalloc.start(25)
  4. def a():
  5. return [i for i in range(300000)]
  6. a = a()
  7. # print(a)
  8. """显示内存分配最多的10个文件"""
  9. snapshot = tracemalloc.take_snapshot() # 快照,当前内存分配
  10. # # top_stats = snapshot.statistics('filename', cumulative=True) # 统计整个文件内存
  11. top_stats = snapshot.statistics('lineno', cumulative=True) # 快照对象的统计
  12. for stat in top_stats[:10]:
  13. print(stat)

记录所有跟踪内存块的当前大小和峰值大小

  1. import tracemalloc
  2. # 开始跟踪内存分配
  3. tracemalloc.start(25)
  4. def a():
  5. return [i for i in range(300000)]
  6. a = a()
  7. # print(a)
  8. """记录所有跟踪内存块的当前大小和峰值大小"""
  9. # 获取由跟踪的内存块的当前大小和峰值大小
  10. current, peak = tracemalloc.get_traced_memory()
  11. print(f"current={current/1024} KIB, peak={peak/1024} KIB")

获取内存块的追溯

  1. import tracemalloc
  2. # 开始跟踪内存分配
  3. tracemalloc.start(25)
  4. def a():
  5. return [i for i in range(300000)]
  6. a = a()
  7. """获取内存块的回溯"""
  8. # 对python分配的内存块的跟踪进行快照
  9. snapshot = tracemalloc.take_snapshot()
  10. # 将统计信息作为 Statistic 实例分组依据
  11. # 'filename' 文件名
  12. # 'lineno' 文件名和行号
  13. # 'traceback' 追溯
  14. # cumulative=True: 累积跟踪的所有帧的内存块大小和计数, 只能是key_type = filename/ lineno
  15. top_stats = snapshot.statistics('traceback')
  16. # 显示最大内存块的回溯的代码
  17. stat = top_stats[0]
  18. print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024))
  19. for line in stat.traceback.format():
  20. print(line)
  21. """
  22. 299744 memory blocks: 10811.4 KiB
  23. File "/tests/base/test17.py", line 16
  24. return [i for i in range(300000)]
  25. File "tests/base/test17.py", line 16
  26. return [i for i in range(300000)]
  27. File "tests/base/test17.py", line 23
  28. a = a()
  29. """