首页 > 编程语言 >python脚本性能分析

python脚本性能分析

时间:2023-01-03 16:02:13浏览次数:44  
标签:脚本 stats socket python 性能 cProfile pstats method 0.000

1.python脚本性能分析

cProfile思路

  • 使用cProfile模块生成脚本执行的统计信息文件
  • 使用pstats格式化统计信息,并根据需要做排序分析处理
  • 使用snakeviz图形化页面显示

2.cProfile

使用cProfile模块生成脚本执行的统计信息文件

1.使用cProfile模块生成脚本执行的统计信息文件

python -m cProfile -o /xxx/out.prof test.py

参数说明: 
使用模块当做脚本运行:-m cProfile 
-o 将profile 结果写入文件而不是标准输出
-s 指定 sort_stats() 排序值之一以对输出进行排序。这仅适用于未提供 -o 的情况
测试的python脚本:test.py

输出信息

ncalls:表示函数调用的次数;
tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
percall:(第一个percall)等于 tottime/ncalls;
cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
filename:lineno(function):每个函数调用的具体信息;

### 输出案列
{'message': 'Number of rows affected: 1', 'state': 'SUCCESS', 'revision': 'eb7bc19a99eeda508410f4533967fb0eb25328e2'}
         5145 function calls (5069 primitive calls) in 1.370 seconds

   Ordered by: internal time
   List reduced from 563 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.327    1.327    1.327    1.327 {method 'recv_into' of '_socket.socket' objects}
        1    0.024    0.024    0.024    0.024 {built-in method _socket.getaddrinfo}
        1    0.007    0.007    0.007    0.007 {method 'connect' of '_socket.socket' objects}
        1    0.006    0.006    0.006    0.006 {built-in method _scproxy._get_proxy_settings}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        2    0.000    0.000    0.000    0.000 {method 'sendall' of '_socket.socket' objects}
        2    0.000    0.000    0.000    0.000 {method 'read' of '_io.BufferedReader' objects}
        1    0.000    0.000    0.000    0.000 {built-in method _scproxy._get_proxies}
       11    0.000    0.000    0.000    0.000 queue.py:121(put)
        4    0.000    0.000    0.000    0.000 {method 'subn' of 're.Pattern' objects}

3.使用pstats分析

使用cProfile分析的结果可以输出到指定的文件中,但是文件内容是以二进制的方式保存的,用文本编辑器打开时乱码。所以,Python提供了一个pstats模块,用来分析cProfile输出的文件内容。

pstats.Stats说明

sort_stats排序参数

有效字符串参数 有效枚举参数 含意
'calls' SortKey.CALLS 调用次数
'cumulative' SortKey.CUMULATIVE 累积时间
'cumtime' N/A 累积时间
'file' N/A 文件名
'filename' SortKey.FILENAME 文件名
'module' N/A 文件名
'ncalls' N/A 调用次数
'pcalls' SortKey.PCALLS 原始调用计数
'line' SortKey.LINE 行号
'name' SortKey.NAME 函数名称
'nfl' SortKey.NFL 名称/文件/行
'stdname' SortKey.STDNAME 标准名称
'time' SortKey.TIME 内部时间
'tottime' N/A 内部时间

strip_dirs()

这个用于 Stats 类的方法会从文件名中去除所有前导路径信息。 它对于减少打印输出的大小以适应(接近) 80 列限制。 这个方法会修改对象,被去除的信息将会丢失。 在执行去除操作后,可以认为对象拥有的条目将使用“随机”顺序,就像它刚在对象初始化并加载之后一样。 如果 strip_dirs() 导致两个函数名变得无法区分(它们位于相同文件名的相同行,并且具有相同的函数名),那么这两个条目的统计数据将被累积到单个条目中。

使用p.strip_dirs()输出
/test/venv/bin/python3 /test/t1.py
{'message': 'Number of rows affected: 1', 'state': 'SUCCESS', 'revision': 'eb7bc19a99eeda508410f4533967fb0eb25328e2'}
         5145 function calls (5069 primitive calls) in 1.683 seconds

   Ordered by: internal time
   List reduced from 563 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.404    1.404    1.404    1.404 {method 'recv_into' of '_socket.socket' objects}
        1    0.262    0.262    0.262    0.262 {built-in method _socket.getaddrinfo}
        1    0.006    0.006    0.006    0.006 {method 'connect' of '_socket.socket' objects}
        1    0.005    0.005    0.005    0.005 {built-in method _scproxy._get_proxy_settings}
        2    0.000    0.000    0.000    0.000 {method 'sendall' of '_socket.socket' objects}
        2    0.000    0.000    0.000    0.000 {method 'read' of '_io.BufferedReader' objects}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        1    0.000    0.000    0.000    0.000 {built-in method _scproxy._get_proxies}
       11    0.000    0.000    0.000    0.000 queue.py:121(put)
        4    0.000    0.000    0.000    0.000 {method 'subn' of 're.Pattern' objects}

未使用p.strip_dirs()输出

区别/test/venv/lib/python3.8/site-packages/urllib3/poolmanager.py:263(connection_from_pool_key)这类信息

/test/venv/bin/python3 /test/t1.py
{'message': 'Number of rows affected: 1', 'state': 'SUCCESS', 'revision': 'eb7bc19a99eeda508410f4533967fb0eb25328e2'}
         5145 function calls (5069 primitive calls) in 1.303 seconds

   Ordered by: internal time
   List reduced from 563 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.263    1.263    1.263    1.263 {method 'recv_into' of '_socket.socket' objects}
        1    0.019    0.019    0.019    0.019 {built-in method _scproxy._get_proxy_settings}
        1    0.007    0.007    0.007    0.007 {method 'connect' of '_socket.socket' objects}
        1    0.003    0.003    0.003    0.003 /test/venv/lib/python3.8/site-packages/urllib3/poolmanager.py:263(connection_from_pool_key)
        1    0.002    0.002    0.002    0.002 {built-in method _socket.getaddrinfo}
        1    0.001    0.001    0.001    0.001 {built-in method builtins.print}
        2    0.001    0.000    0.001    0.000 {method 'read' of '_io.BufferedReader' objects}
        1    0.000    0.000    0.000    0.000 {built-in method _scproxy._get_proxies}
      147    0.000    0.000    0.000    0.000 /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/os.py:748(encode)
        2    0.000    0.000    0.000    0.000 {method 'sendall' of '_socket.socket' objects}

sort_stats()

参考pstats.Stats说明,根据提供的条件对其进行排序。

import pstats
p = pstats.Stats('/xxx/out.prof')

# 根据NAME和FILE进行排序
p.sort_stats(SortKey.NAME, SortKey.FILE) 
# 输出全部
p.print_stats()

提供的参数(如果有)可用于将列表限制为重要条目。最初,列表被视为一组完整的概要函数。每个限制要么是一个整数(选择行数),要么是一个介于0.0和1.0之间(包括0.0和1.0)的小数(选择行的百分比),要么是一个将被解释为正则表达式的字符串(模式与打印的标准名称匹配

import pstats
p = pstats.Stats('/xxx/out.prof')

# 输出前10行
p.print_stats(10)

# 首先将打印限制在列表的前10%,然后仅打印属于文件名的函数 .*foo: 
p.print_stats(.1, 'foo:')

# 将列表限制为具有文件名的所有函数 .*foo: ,然后继续只打印前10%的内容。
p.print_stats('foo:', .1)

dump_stats()

import pstats

# 保存信息到文件中
p=pstats.Stats('/xxx/out.prof')

# 排序
p.sort_stats('calls')

# 把排序完后的内容输出到新的文件中
p.dump_stats('/xxx/xxx.prof')
import pstats

p=pstats.Stats('/xxx/out.prof')

# 如果想知道有哪些函数调用了sum_num
p.print_callers(0.5, "sum_num")
import pstats

p=pstats.Stats('/xxx/out.prof')

# 查看test()函数中调用了哪些函数
p.print_callees("test")

4.图形化工具

安装snakeviz

pip3 install snakeviz

查看是否安装完成

snakeviz -v

snakeviz 2.1.1

使用snakeviz

使用cProfile输出的文件或者pstats输出的文件进行分析

snakeviz /xxx/xxx.prof 
snakeviz web server started on 127.0.0.1:8080; enter Ctrl-C to exit
http://127.0.0.1:8080/snakeviz/%2FUsers%2Flxd670%2Ftest_pg3%2Fa.prof

5.使用代码

函数

def main():
  ...

if __name__ == '__main__':
    import cProfile
    import pstats
    with cProfile.Profile() as pf:
        main()
    stats = pstats.Stats(pf)
    stats.strip_dirs()
    # 按时间排序
    stats.sort_stats(pstats.SortKey.TIME)
    # 在终端打印前10行信息
    stats.print_stats(10)
    # 把排序过滤后的信息输出到xxx.prof文件中
    stats.dump_stats('./xxx.prof')

协程函数

async def main():
  ...

if __name__ == '__main__':
    import cProfile
    import pstats
    with cProfile.Profile() as pf:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(main())
    stats = pstats.Stats(pf)
    stats.strip_dirs()
    stats.sort_stats(pstats.SortKey.TIME)
    stats.print_stats(10)
    stats.dump_stats('./xxx.prof')

标签:脚本,stats,socket,python,性能,cProfile,pstats,method,0.000
From: https://www.cnblogs.com/lxd670/p/17022499.html

相关文章