暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

python 内存系列(10)-linux 下 性能分析工具py-spy压测下分析Flask程序

小儿来一壶枸杞酒泡茶 2021-03-10
2647

前言

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

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

linux上 Py-Spy 分析已在运行中的Flask程序实践

安装Py-Spy

pip  install py-spy

验证安装:


[root@localhost xingnengfenxi]# py-spy -h
py-spy 0.3.4
Sampling profiler for Python programs

USAGE:
    py-spy <SUBCOMMAND>

OPTIONS:
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    record    Records stack trace information to a flamegraph, speedscope or raw file
    top       Displays a top like view of functions consuming CPU
    dump      Dumps stack traces for a target program to stdout
    help      Prints this message or the help of the given subcommand(s)
[root@localhost xingnengfenxi]#


上传示例代码到我们的运行目录下:

-flaskmain.py

'''
Author: 小钟同学
objectDescription: 项目描述
Date: 2021-03-07 21:48:40
LastEditors: 308711822@qq.com
LastEditTime: 2021-03-10 09:40:07
FilePath: \py\flaskmain.py
Version: 1.0
'
''
from flask import Flask, jsonify
import time


import tracemalloc


app = Flask(__name__)


@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='0.0.0.0', port=8888, debug=True)


第1种 、使用分析进程ID的方式,生产火焰图分析

使用分析进程ID的方式,通常分析的是已运行的进程。

[root@localhost xingnengfenxi]# python flaskmain.py

查询我们的python flaskmain.py运行后的对于的PID

[root@localhost xingnengfenxi]# ps -ef|grep flaskmain
root       8255   6320  4 10:16 pts/0    00:00:00 /root/.pyenv/versions/3.7.3/bin/python flaskmain.py
root       8300   8255  4 10:16 pts/0    00:00:00 /root/.pyenv/versions/3.7.3/bin/python /data/www/xingnengfenxi/flaskmain.py
root       8304   6638  0 10:16 pts/1    00:00:00 grep --color=auto flaskmain
[root@localhost xingnengfenxi]#


提取pid:


root       8300   8255  0 10:16 pts/0    00:00:00 /root/.pyenv/versions/3.7.3/bin/python /data/www/xingnengfenxi/flaskmain.py


分析当前进程情况:


[root@localhost xingnengfenxi]# py-spy record -o profile.svg --pid 8300
py-spy> Sampling process 100 times a second. Press Control-C to exit.


使用命令的方式启动分析,提示出现以下的错误信息:使用:

# OR
py-spy record -o profile.svg -- python myprogram.py 方式运行的flask主程序会有下面的错误提示

错误内容:

[root@localhost xingnengfenxi]# py-spy record -output profile.svg -python flaskmain.py
thread 'main' panicked at 'invalid pid: ParseIntError { kind: InvalidDigit }', src/config.rs:262:64
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[root@localhost xingnengfenxi]# py-spy record -output profile.svg -python flaskmain.py

随机的高并发压测我们的线上的API接口

1、新建测试计划,保持此压测的文件
2、添加一个压测的线程组
3、给当前线程组添加Http请求压测
4、配置Http请求压测信息(压测地址和信息)

基本信息配置:

信息线程组信息配置:

线程数:表示发起多少独立的线程请求 Ramp-up时间:表示我需要用多少时间把上面线程数处理完成,0 表示瞬间并发,不需要时间,适用于高并发压测 循环次数:表示寻发送送法几次 发送完成200 再法三次200

5、给HTTP请求配置一个聚合报告监听器
6、点击开始进行压测

查看我们的性能分析输出


[root@localhost xingnengfenxi]# py-spy record -o profile.svg --pid 8516
py-spy> Sampling process 100 times a second. Press Control-C to exit.

py-spy> 1.00s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 1.84s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 2.72s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 3.63s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 4.49s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 5.38s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 6.11s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 6.85s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 7.66s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 8.49s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 9.15s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 9.87s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 10.58s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 11.30s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 12.03s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 13.01s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 13.92s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 14.72s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 15.47s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 16.20s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 16.90s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 16.98s behind in sampling, results may be inaccurate. Try reducing the sampling rate
py-spy> 16.15s behind in sampling, results may be inaccurate. Try reducing the sampling rate


导出性能分析火焰图profile.svg

分析火焰图profile.svg

來自阮一峰老师的火焰图的解说:

  • 火焰图:用来展示 CPU 的调用栈

  • py-spy 生成的火焰图方向:其火焰是向下

  • y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。

  • x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

  • 颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。

  • 总结:火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。

  • 通过生成火焰图分析程序瓶颈,看profile.svg图中最下方哪个峰顶是平的,那么程序的性能问题就可以从那入手去解决。

第2种 、使用分析进程ID的方式,通过top类似linux 系统top命令输出的实时视图

[root@localhost xingnengfenxi]# py-spy top --pid 8516
# OR
py-spy top -- python myprogram.py (分析flask等的会有异常)

一遍压测一边看观察:

图示相关的参数说明:

  • 按%Own排序:当前在该函数中花费的时间的百分比
  • 按%Total排序:函数及其子级中当前的时间百分比
  • 按OwnTime排序:函数中花费的总时间
  • 按TotalTime排序:该函数及其子项花费的总时间

最主要其实我们的可以通过OwnTime比较直接的定位程序运行中,所占比消耗时间最多的函数

第3种 、使用分析进程ID的方式,通过dump显示每个线程的调用栈

分析命令:

py-spy dump --pid 8516

分析结果:


[root@localhost xingnengfenxi]# py-spy dump --pid 8516
Process 8516: /root/.pyenv/versions/3.7.3/bin/python /data/www/xingnengfenxi/flaskmain.py
Python v3.7.3 (/root/.pyenv/versions/3.7.3/bin/python3.7)

Thread 8516 (idle): "MainThread"
    run (werkzeug/_reloader.py:214)
    run_with_reloader (werkzeug/_reloader.py:337)
    run_simple (werkzeug/serving.py:1050)
    run (flask/app.py:990)
    <module> (flaskmain.py:32)
Thread 8518 (idle): "Thread-1"
    select (selectors.py:415)
    serve_forever (socketserver.py:232)
    serve_forever (werkzeug/serving.py:777)
    inner (werkzeug/serving.py:1009)
    run (threading.py:865)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)
[root@localhost xingnengfenxi]#


说明

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

End

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


文章转载自小儿来一壶枸杞酒泡茶,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论