ITPub博客

首页 > 数据库 > 数据库开发技术 > python 内存系列(11)-分析程序堆栈信库Pyinstrument

python 内存系列(11)-分析程序堆栈信库Pyinstrument

原创 数据库开发技术 作者:程序员小钟同学 时间:2021-03-10 14:06:20 0 删除 编辑

前言

纯属个人实践中相关经验之谈,如有纰漏,还希望大佬们多多提点!

小钟同学 | 文  【原创】| QQ:308711822


调用栈性能分析

在我们的开发相关程序的时候,深入到堆栈内部进行分析程序性能的时候,在前面都讲了一些比较好的工具,这里在实践一个Pyinstrument的库的使用。

这个库可以帮我们再执行程序过程中记录下程序堆栈信息,通过对堆栈的信息进行分析找出耗时的程序代码。

它也合适于集成到一些我们的流程的一些Web开发框架中进行使用。如:Django、Flask等。

支持:PyTool支持Python2.7和3.3+。

官网地址:

https://github.com/joerick/pyinstrument

1.库的安装

pip install pyinstrument

使用的最简示例-分析特定的代码块

它可以和我们的之前分享的trancemalloc一样,内嵌到我们需要分析的代码块进行对应的代码块性能。示例如:

1.代码内嵌方式,控制台输出

from pyinstrument import Profiler
import random

## 创建Profiler对象,并且启动
profiler = Profiler()
profiler.start()

# code you want to profile


class A():
    def __init__(self):
        super().__init__()

    def randomlist(self, n):
        lists = []
        l = [random.random() for i in range(n)]
        l.sort()
        for v in l:
            lists.append(v)
        return lists

    def randomlist2(self, n):
        lists = []
        l = [random.random() for i in range(n)]
        l.sort()
        for v in l:
            lists.append(v)
        return lists


A().randomlist(20000000)

profiler.stop()

print(profiler.output_text(unicode=True, color=True))


最终分析的结果为:

(.venv) PS D:\code\vscode\py> & d:/code/vscode/py/.venv/Scripts/python.exe d:/code/vscode/py/ceshi2.py

  _     ._   __/__   _ _  _  _ _/_   Recorded: 12:05:41  Samples:  8199
 /_//_/// /_\ / //_// / //_'/ //     Duration: 23.990    CPU time: 23.891
/   _/                      v3.2.0

Program: d:/code/vscode/py/ceshi2.py

23.990 <module>  ceshi2.py:9
├─ 22.857 randomlist  ceshi2.py:80
│  ├─ 14.174 list.sort  <built-in>:0
│  │     [2 frames hidden]  <built-in>
│  ├─ 3.826 [self]
│  ├─ 3.781 <listcomp>  ceshi2.py:82
│  │  ├─ 2.745 [self]
│  │  └─ 1.036 Random.random  <built-in>:0
│  │        [2 frames hidden]  <built-in>
│  └─ 1.076 list.append  <built-in>:0
│        [2 frames hidden]  <built-in>
└─ 1.133 [self]


(.venv) PS D:\code\vscode\py> 

2.代码内嵌方式,浏览器打开输出:

from pyinstrument import Profiler
import random

profiler = Profiler()
profiler.start()

# code you want to profile


class A():
    def __init__(self):
        super().__init__()

    def randomlist(self, n):
        lists = []
        l = [random.random() for i in range(n)]
        l.sort()
        for v in l:
            lists.append(v)
        return lists

    def randomlist2(self, n):
        lists = []
        l = [random.random() for i in range(n)]
        l.sort()
        for v in l:
            lists.append(v)
        return lists


A().randomlist(200000)

profiler.stop()

# print(profiler.output_text(unicode=True, color=True))
profiler.open_in_browser(timeline=True)

浏览器最终展示:

3.命令行方式启动且输出文件:

如需分析代码:

class A():
    def __init__(self):
        super().__init__()

    def randomlist(self, n):
        lists = []
        l = [random.random() for i in range(n)]
        l.sort()
        for v in l:
            lists.append(v)
        return lists

    def randomlist2(self, n):
        lists = []
        l = [random.random() for i in range(n)]
        l.sort()
        for v in l:
            lists.append(v)
        return lists


A().randomlist(20000000)

使用下面的命令方式分析上面的代码:

pyinstrument  --outfile=result_info.html -r html --hide=EXPR demo.py
  • --outfile= 指定输出文件名称
  • -r 指定输出的文件类偶像
  • --hide=EXPR 隐藏内置库调用过程中的信息

查看相关的文件信息

结合Flask框架的使用:

思路:我们的可以分析每次请求进来的时候,启动Profiler,然后请求是结束的时候结束Profiler。利用flask的钩子函数就可以做到:

示例如:


from pyinstrument import Profiler
from flask import Flask, g, make_response, request,jsonify
import time

app = Flask(__name__)

@app.before_request
def before_request():
    g.profiler = Profiler()
    g.profiler.start()




@app.after_request
def after_request(response):
    g.profiler.stop()
    output_html = g.profiler.output_html()
    return make_response(output_html)




@app.route('/')
def line_test():

    for item in range(5):
        print(item)
        time.sleep(0.2)

    return jsonify({'code': 200})


if __name__ == '__main__':

    app.run(host='127.0.0.1', port=8565, debug=True)

然后我们的请求我们的地址:http://127.0.0.1:8565/ 最终我们的返回的结果是我们的堆栈信息图:

pyinstrument与profile 的不同点:

  • Pyinstrument 统计分析器

1.每隔1ms记录一次堆栈的情况,它不会跟踪程序进行的每个函数调用.减少系统开销

2.记录整个堆栈,因此可以完美的展示调用关系,并且会默认隐藏内置木块和标准库的调用信息。

  • profile 跟踪分析器

1.需大量调用探查器,可能会扭曲结果。

2.无法明确相关调用关系

说明

部分的图或资料来互联网收集整理,如有侵权,烦请联系,我会立即进行删除。

End

纯属个人实践中相关经验之谈,如有纰漏,还希望大佬们多多提点!小钟同学 | 文  【原创】| QQ:308711822


原文作者:程序员小钟同学;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2021-02-20

  • 博文量
    224
  • 访问量
    111698