PyInstrument-关注慢速部分的统计Python配置文件

2020-10-20 22:46:54

PyInstrument是一个Python分析器。分析器是一种工具,可以帮助您优化代码-使其速度更快。这听起来很明显,但是要获得最大的速度提升,您应该专注于程序中最慢的部分。PyInstrument会帮助您找到它!

要从GIT签出运行PyInstrument,有一个构建步骤。看看如何贡献更多信息。

直接从命令行调用PyInstrument。不是编写python script.py,而是输入pyInstrument script.py。您的脚本将正常运行,并且在结束时(或者当您按^C时),PyInstrument将输出彩色摘要,显示大部分时间都花在哪里。

用法:pyInstrument[选项]scriptfile[arg]...选项:--version show program的版本号和exit-h,--help显示此帮助消息并退出--load-prev=ID如果不运行脚本,请加载以前的报表-m module_name将库模块作为脚本运行,如';python-m module';-o OUTFILE,--outfile=OUTFILE save to<;outfile>;-r渲染器,--renender=渲染器应如何呈现报表。以下内容之一:text&39;、html&39;、';json&39;或到渲染器类的python导入路径-t、--timeline呈现为时间线-保留顺序,并且不压缩重复调用--ide=expr glob样式模式,匹配要隐藏其帧的文件路径。默认为';*/lib/*';。--Hide-regex=与要隐藏其帧的文件路径匹配的REGEX regex。如果--HIDE没有给予足够的控制,那就有用了。--show-all(仅限文本渲染器)显示外部库代码--unicode(仅限文本渲染器)强制Unicode文本输出--no-unicode(仅限文本渲染器)强制ascii文本输出--color(仅限文本渲染器)强制ansi彩色文本输出--no-color(仅限文本渲染器)强制不输出彩色文本。

ProTip:-r html会给你一个HTML格式的交互式个人资料报告--你真的可以通过这种方式来探索!

安装后,将?PROFILE添加到请求URL的末尾以激活探查器。您的请求将照常运行,但您不会得到响应,而是会在网页中获得pyInstrument对请求的分析。

如果您正在编写API,当您想要分析某些内容时,更改URL并非易事。在这种情况下,将PYINSTRUMENT_PROFILE_DIR=';PROFILES=#39;添加到settings.py。PyInstrument将分析每个请求,并将HTML输出保存到您工作目录中的文件夹配置文件中。

如果要根据请求显示分析页面,可以将PYINSTRUMENT_SHOW_CALLBACK定义为函数的虚线路径,该函数用于确定是否应该显示页面。您可以提供自己的函数回调(Request),它在settings.py中返回True或False。

从flask import Flask,g,make_response,请求app=flask(__Name__)@app。BEFORE_REQUEST定义BEFORE_REQUEST():如果请求中的";配置文件";。参数:g.profiler=profiler()g.profiler。Start()@app。AFTER_REQUEST定义AFTER_REQUEST(Response):如果没有hasattr(g,";profiler";):返回响应g.profiler。Stop()output_html=g.profiler。Output_html()返回make_response(Output_Html)。

这将检查每个请求上的?Profile查询参数,如果找到,则开始分析。在分析器运行的每个请求之后,它创建html输出并返回该输出,而不是实际的响应。

我希望有更多的方式使用PyInstrument进行分析--例如其他Web框架。鼓励使用PRS!

PyInstrument是一个统计分析器-它不会跟踪您的程序进行的每个函数调用。取而代之的是,它每1ms记录一次呼叫堆栈。

与其他分析器相比,这提供了一些优势。首先,统计分析器比跟踪分析器开销低得多。

█0.33s。

█0.43s。

██0.61s

██...██6.79s。

但低开销也很重要,因为它会扭曲结果。当使用跟踪探查器时,进行大量Python函数调用的代码会大量调用探查器,从而使其速度变慢。这会扭曲结果,并可能导致您优化程序的错误部分!

标准的Python分析器配置文件和cProfile向您显示一个函数列表,按每个函数花费的时间排序。这很好,但是很难解释为什么调用这些函数。了解调用这些函数的原因以及涉及到用户代码的哪些部分会更有帮助。

例如,假设我想弄清楚为什么Django中的Web请求速度很慢。如果我使用cProfile,我可能会得到这样的结果:

151940个函数调用(147672个基元调用),按以下顺序排序:累计时间n调用总时间每次调用累计时间每次调用文件名:lineno(函数)1 0.000 0.000 1.696 1.696配置文件:0(<;代码对象<;模块>;位于0x1053d6a30,文件";./Manage.py";,行2>;)1 0.001 0.001 1.693 1.693 manage.py:2(<;模块>;)1 0.000 0.000 1.586 1.586__init__.py:394(EXECUTE_FROM_COMMAND_LINE)1 0.000 0.000 1.586 1.586__INIT__.py:350(执行)1 0.000 0.000 1.142 1.142__INIT__.py:254(获取命令)430.013 0.000 1.124 0.026__INIT__.py:1(<;模块&>;)0.008 0.000 0.000 1.062 0.003 re.py:226(_COMPILE)158 0.005 0.000 1.048 0.007 SRE_COMPILLE.py:496(编译)1 0.001 0.001 1.0421.042__init__.py:78(Get_Commands)1530.001 0.000 1.0360.007re.py:188(编译)106/1020.000.000 1.0300.010_init_.py:52(_。_getattr__)1 0.000 0.000 1.029 1.029__init__.py:31(_Setup)1 0.000 0.000 1.021 1.021__init__.py:57(_CONFIGURE_LOGGING)2 0.002 0.001 1.011 0.505log.py:1(<;模块>;)。

PyInstrument记录整个堆栈,因此跟踪昂贵的呼叫要方便得多。默认情况下,它还隐藏库框架,让您专注于影响性能的应用程序/模块。

_._/_/记录:14:53:35样本:13/_//_/\/_/';/持续时间:3.131 CPU时间:0.195/_/v3.0.0b3程序:示例/django_example/manage.py runserver--无线程--noreload3.131<;模块>;Py:2└─3.118 EXECUTE_FROM_COMMAND_LINE Django/CORE/MANAGEMENT/__INIT__.py:378[473帧隐藏]Django,socketserver,选择器,wsgi...。2.836选择选择器.py:365 0.126_GET_RESPONSE Django/CORE/Handler/base.py:96└─0.126 HELLO_WORLD Django_Example/Views.py:4。

PyInstrument使用挂钟时间记录持续时间。当您正在编写下载数据、读取文件和与数据库对话的程序时,所有这些时间都包含在pyInstrument跟踪的时间中。

这在调试性能问题时非常重要,因为Python经常被用作其他服务之间的粘合剂语言。问题可能不在您的程序中,但您应该仍然能够找到程序运行缓慢的原因。

PyInstrument每1ms中断一次程序,并在该点记录整个堆栈。它使用C扩展和PyEval_SetProfile来实现这一点,但是每1ms只读取一次读数。有关更多信息,请查看此博客帖子。

你可能会对组成一份报告的样本如此之少感到惊讶,但别担心,这不会降低准确性。默认间隔1ms是记录堆栈帧的下限,但如果在单个函数调用中花费的时间较长,则会在该调用结束时记录。因此,这些样本实际上被捆绑在一起,并在最后录制下来。

添加了在C函数中跟踪时间的功能。次要注意-由于Python记录帧的方式有限制,PyInstrument将C函数记录为叶子函数所花费的时间。Python->;C->;Python记录为Python->;Python,但Python->;Python->;C的属性将正确。(#103)。

在Django中间件上添加了PYINSTRUMENT_SHOW_CALLBACK选项,以添加显示配置文件的条件(可用于在实时服务器上运行pyInstrument!)。

修复了Django中间件中由于Unicode错误而无法写入文件的错误。

修复了Windows上Django中间件的错误,在该错误中,由于我们试图在配置文件路径中放置非法字符';?';,所以配置文件将失败。(#66)。

添加--show和--show-regex选项,以标记要显示的某些文件。这有助于分析特定模块内部的情况,而不是隐藏。例如,pyInstrument--show';*/symmy/*&39;script.py。

PyInstrument现在将通过您默认使用的库隐藏跟踪。因此,它不会向您展示通过外部内容(如urllib)内部的大量框架,而是让您专注于您的代码。

';条目';会显示隐藏组的框架,这样您就可以知道问题出在哪个呼叫上。

组中非常慢的帧也会显示出来,例如套接字上的Read调用。

其他指标显示在跟踪顶部-时间戳、样本数、持续时间、CPU时间。

隐藏代码由代码文件路径上的--HIDE或--HIDE-regex选项控制。

--HIDE=expr glob样式模式,匹配要隐藏其帧的文件路径。默认为';*/lib/*';。--Hide-regex=与要隐藏其帧的文件路径匹配的REGEX regex。如果--HIDE没有给予足够的控制,那就有用了。

因为现在有几个呈现选项,所以您可以使用--load-prev-pyInstrument加载前一个性能分析会话来保存最后10个会话。

(内部)当记录时间线时,框架树现在完全是线性的,允许创建超精确的框架图。

(内部)HTML渲染器已被重写为Vue.js应用程序。所有控制台的改进也适用于HTML输出,另外它还具有交互性。

大重构!录音机已被移除。帧录制现在是Profiler对象的内部。这意味着帧对象更加通用,这为……铺平了道路。

处理器!这些是改变树以雕刻输出的函数,渲染器使用它们将输出过滤成正确的形式。现在,分析器不是时间聚合记录器,而是只使用时间线样式的记录(这无论如何开销更低),并且聚合是作为一个处理步骤来完成的。

这样做的结果是,现在可以更容易地更改树来过滤掉东西,并做一些更高级的事情,比如组合我们不关心的框架。在v3.0中还会有更多使用此功能的功能!

Importlib框架被移除-您将根本看不到它们。他们的孩子被保留下来,所以进口只是透明的。

当运行pyInstrument--html并且您没有将输出通过管道传输到文件时,pyInstrument会将控制台输出写入一个临时文件,然后在浏览器中打开该文件。

添加了对通过命令行使用pyInstrument运行模块的支持。新的语法是-m标志,例如pyInstrument-m模块名称!普瑞。

修复由于多线程使用pyInstrument而导致的崩溃。修复程序位于C扩展中,位于https://github.com/joerick/pyinstrument_cext/pull/3

修复了用于分析堆栈上有大量帧的程序时的最大递归错误。

PyInstrument使用一种新的剖析模式。Pyinterument不使用信号,而是使用基于PyEval_SetProfile的新统计分析器。这意味着在使用PyInstrument时不再有主线程限制,不再有IO错误,也不需要单独的More';setprofile';模式!

渲染器。用户可以通过Profiler.output()上的renender参数或命令行上的--renderer参数自定义PyInstrument以使用替代渲染器。

录音机。为了支持PyInstrument的其他使用案例(例如火焰图表),PyInstrument现在有一个时间线记录器模式。此模式以线性方式记录捕获的帧,因此可以在atimeline上查看程序执行情况。

PyInstrument命令。现在可以通过运行$pyInstrument script.py从Shell分析python脚本。这现在等同于python-m pyInstrument。谢谢@asmeurer!

向Django界面添加了PYINSTRUMENT_PROFILE_DIR选项,该选项会将所有请求的配置文件记录到指定文件夹中的文件。用于分析API调用。

要从git存储库或源代码签出运行pyInstrument,必须先运行。

这将编译HTML输出所需的Javascript代码。您将需要安装节点(管道安装不需要节点,因为控制盘中已经预置了Javascript)。