Python asyncio 性能分析

news2024/10/6 18:41:20

文章目录

  • 1. 工具
    • 1.1 cProfile
    • 2.1 yappi
  • 2. 可视化
    • 2.1 SnakeViz
    • 2.2 gprof2dot

1. 工具

1.1 cProfile

一般对分析python性能的工具都会用cprofile。但是这玩意对多线程和asyncio的支持并不友好,如果用它对asyncio分析,会发现CPU都耗费在了poll上面,无法确定到底耗费在哪些协程上。

例如会出现python - What is correct way to use cProfile with asyncio code? - Stack Overflow这样的问题。

用法:

python3 -m cProfile -o test.prof  test2.py

运行完会生成一个test.prof文件,本文第2节介绍如何通过可视化工具查看这个文件。
也可以通过cprofilev来查看。

pip install cprofilev 

cproilev

cprofilev -f ./test.prof

浏览器中打开运行上方代码后生成的ip和端口号,如下:
在这里插入图片描述

2.1 yappi

GitHub - sumerc/yappi: Yet Another Python Profiler, but this time thread&coroutine&greenlet aware.

这个工具可以测多线程、asycio等多种场景。
其实,CPython本身就自带三个调优工具,它们分别是cProfile,Profile和hotshot。这三个工具对多线程的Python程序的性能剖析支持得都不好,开发者必须想办法分别对线程进行profile,然后再把结果合并。而yappi的出现就是为了解决Python多线程程序的profile问题。

安装:

pip install yappi

下面先通过一个简单案例介绍使用yappi库,这是对多线程程序进行profile的代码例子。需要注意的是,yappi.set_clock_type函数的参数,如果是cpu,代表统计的是在CPU上执行的时间,如果是wall,代表统计的是持续的时间。

import yappi
if __name__ == "__main__":
    # yappi.set_clock_type("wall")
    yappi.set_clock_type("cpu")
    yappi.start()
    for i in range(10):
        t = threading.Thread(target=sum, args=(100, i,), name="hello"+str(i))
        t.start()
    main_thread = threading.currentThread()

    for t in threading.enumerate():
        if t is not main_thread:
            t.join()
    yappi.get_func_stats().print_all()
    yappi.get_thread_stats().print_all()

你可以按上面这个例子改造你自己多线程程序,然后运行,就会得到如下的分析结果。

Clock type: CPU
Ordered by: totaltime, desc

name                                                ncall            tsub                ttot                tavg                
..ns/2.7/lib/python2.7/threading.py:752 Thread.run  10               0.000137            2.428557            0.242856          
..thub/Asgard/samples/yappi/yappi_sample.py:16 sum  10               0.000089            2.428420            0.242842          
..ub/Asgard/samples/yappi/funcs.py:5 consumer_time  10               0.414581            2.428331            0.242833          
..s/2.7/lib/python2.7/random.py:238 Random.randint  109362           0.729320            1.926393            0.000018          
..2.7/lib/python2.7/random.py:175 Random.randrange  109362           0.860899            1.197073            0.000011          
../2.7/lib/python2.7/threading.py:726 Thread.start  10               0.000224            0.001801            0.000180          
..7/lib/python2.7/threading.py:656 Thread.__init__  10               0.000283            0.001404            0.000140          
..s/2.7/lib/python2.7/threading.py:603 _Event.wait  10               0.000152            0.001217            0.000122          
..7/lib/python2.7/threading.py:309 _Condition.wait  12               0.000423            0.001210            0.000101          
..2.7/lib/python2.7/threading.py:866 Thread.__stop  10               0.000255            0.000956            0.000096          
..s/2.7/lib/python2.7/threading.py:911 Thread.join  10               0.000257            0.000761            0.000076          
..ersions/2.7/lib/python2.7/threading.py:542 Event  10               0.000068            0.000587            0.000059          
../python2.7/threading.py:400 _Condition.notifyAll  10               0.000143            0.000580            0.000058          
..ons/2.7/lib/python2.7/threading.py:242 Condition  20               0.000169            0.000523            0.000026          
..7/lib/python2.7/threading.py:561 _Event.__init__  10               0.000153            0.000519            0.000052          
..lib/python2.7/threading.py:373 _Condition.notify  10               0.000191            0.000403            0.000040          
..b/python2.7/threading.py:260 _Condition.__init__  20               0.000286            0.000354            0.000018          
../python2.7/threading.py:300 _Condition._is_owned  22               0.000156            0.000292            0.000013          
..ib/python2.7/threading.py:709 Thread._set_daemon  10               0.000111            0.000242            0.000024          
...7/lib/python2.7/threading.py:1152 currentThread  21               0.000137            0.000205            0.000010          
..s/2.7/lib/python2.7/threading.py:64 Thread._note  54               0.000201            0.000201            0.000004          
...7/lib/python2.7/threading.py:59 Thread.__init__  40               0.000135            0.000135            0.000003          
..2.7/threading.py:297 _Condition._acquire_restore  12               0.000087            0.000130            0.000011          
..hon2.7/threading.py:294 _Condition._release_save  12               0.000071            0.000108            0.000009          
../2.7/lib/python2.7/threading.py:570 _Event.isSet  20               0.000061            0.000061            0.000003          
..b/python2.7/threading.py:1008 _MainThread.daemon  10               0.000037            0.000037            0.000004          
..ns/2.7/lib/python2.7/threading.py:1183 enumerate  1                0.000016            0.000021            0.000021          

name           id     tid              ttot      scnt        
Thread         3      123145399676928  0.087168  37        
Thread         1      123145391263744  0.087128  138       
Thread         8      123145420709888  0.087124  140       
Thread         9      123145424916480  0.087121  40        
Thread         2      123145395470336  0.087109  27        
Thread         6      123145412296704  0.087088  92        
Thread         5      123145408090112  0.087084  125       
Thread         7      123145416503296  0.087072  51        
Thread         4      123145403883520  0.087069  139       
Thread         10     123145429123072  0.087030  132       
_MainThread    0      140735541031744  0.023092  13     

上半部分是函数调用统计。

  • ncall: 调用次数
  • tsub: 不包含子函数所占用的CPU时间
  • ttot: 包含子函数所占用的CPU时间
  • tavg: 包含子函数时平均占用CPU时间

下半部分是所有线程的统计结果。

  • tid 线程
  • idttot 线程总的CPU占用时间
  • scnt 线程被调度到CPU上的次数

再看一个例子,通过运行下方例子就会输出每个函数/协程所占用的时间,并生成一个test.prof文件:

import asyncio
import sys
import yappi
 
test_time = 5  # 测试时间
 
 
async def exit():
    await asyncio.sleep(5)
    yappi.get_func_stats().print_all()
    yappi.stop()
    stats = yappi.convert2pstats(yappi.get_func_stats())
    stats.dump_stats("test.prof")
    asyncio.get_event_loop().stop()
    sys.exit(0)
 
 
async def do_something(num):
    for i in range(num):
        i = i+1
        await asyncio.sleep(0)
 
 
async def test1():
    await do_something(10000)
 
 
async def test2():
    await do_something(100000)
 
 
async def main():
    asyncio.get_event_loop().create_task(exit())
    while True:
        await test1()
        await test2()
yappi.set_clock_type("cpu")
yappi.start()
loop = asyncio.get_event_loop()
with yappi.run():
    loop.run_until_complete(main())
 

输出如下图:
在这里插入图片描述

2. 可视化

2.1 SnakeViz

可以针对上面工具生成的prof文件进行分析,然后生成分析结果可以直观地看到cpu时间都耗费在哪里了。

使用方法:

pip install snakeviz
snakeviz test.prof 

就会自动打开一个网页来展示分析的情况。
snakeviz

snakeviz

2.2 gprof2dot

gprof2dot可以将prof文件生成一个图片。

安装:

apt-get install graphviz
pip install gprof2dot

运行:

gprof2dot -f pstats test.prof | dot -Tpng -o output.png

生成的图片如下图所示
在这里插入图片描述
参考文献:

  • 查看prof文件|阅读prof文件
  • 用yappi对Python程序性能调优
  • The Python Profilers — Python 3.10.4 documentation
  • Python asyncio 性能分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/947097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态维护直径 || 动态维护树上路径 || 涉及LCA点转序列 || 对欧拉环游序用数据结构维护:1192B

https://www.luogu.com.cn/problem/CF1192B 对于直径的求法,常用dp或两次dfs,但如果要动态维护似乎都不太方面,那么可以维护树上路径最大值。 树上路径为: d e p u d e p v − 2 d e p l c a ( u , v ) dep_udep_v-2\times de…

如何实现AI的矢量数据库

推荐:使用 NSDT场景编辑器 助你快速搭建3D应用场景 然而,人工智能模型有点像美食厨师。他们可以创造奇迹,但他们需要优质的成分。人工智能模型在大多数输入上都做得很好,但如果它们以最优化的格式接收输入,它们就会真正…

Python的pymysql模块与MySQL数据库的互动:基础与实例

Python的pymysql模块与MySQL数据库的互动:基础与实例 一、连接数据库二、创建游标三、执行SQL命令四、关闭连接 在Python的世界里,操作MySQL数据库最常用的库就是pymysql。 pymysql是一个灵活且易于使用的库,它允许我们以Python的方式操作MyS…

网络安全研究和创新:探讨网络安全领域的最新研究成果、趋势和创新技术,以及如何参与其中。

第一章:引言 随着数字化时代的到来,网络安全变得比以往任何时候都更加重要。无论是个人、企业还是国家,都面临着日益复杂和隐蔽的网络威胁。为了确保我们的信息和资产的安全,网络安全研究变得至关重要。本文将深入探讨网络安全领…

搭建 Qt6 + Visual Studio 开发环境

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 在 Windows 中,如果想要开发 Qt 应用程序,可以选择多种方式: Qt Creator MinGW 编译器Qt Creator MSVC 编译器Visual Studio&#xff0…

【前车之鉴】: 2023最新教程-将java程序打包到maven私服的正确打开方式,详细流程介绍不怕你掌握不了

文章目录 为什么看这篇整体流程1. 注册账号【首次需要】2. 工单申请【新项目必须】3. 项目配置【新项目必须】4. 授权认证【新项目必须】5. 一键发布 最后也很重要 为什么看这篇 一是当前网络上一些博客有遗漏部分,这里做补充,二是网上思路没错&#xff…

Ansible自动化运维工具(二)

目录 (6)copy模块 (7)file模块 ​编辑​编辑(8)hostname模块 (9)ping模块 (10)yum 模块 (11)service/system模块 ​编辑 ​…

11.TIM定时中断

STM32标准库开发-总目录-传送门 目录 TIM简介 定时器类型 基本定时器 1.基本定时器时基单元 2.时基单元的工作流程 3.主模式触发DAC的功能 通用定时器 1.通用定时器与基本定时器异同 2.内外时钟源选择功能 3. 编码器接口功能 4.主从触发模式功能 5.输出比较功能 6…

Excel:通过Lookup函数提取指定文本关键词

函数公式:LOOKUP(9^9,FIND($G 2 : 2: 2:G 6 , C 2 ) , 6,C2), 6,C2),G 2 : 2: 2:G$6) 公式解释: lookup第一参数为9^9:代表的是一个极大值的数据,查询位置里面最接近这一个值的数据;lookup第二参数用find函数代替&am…

【ES】笔记-集合介绍与API

集合是一种不允许值重复的顺序数据结构。 通过集合我们可以进行并集、交集、差集等数学运算, 还会更深入的理解如何使用 ECMAScript 2015(ES2015)原生的 Set 类。 构建数据集合 集合是由一组无序且唯一(即不能重复)的项组成的。该数据结构使用了与有限集合相同的数…

基于AVR128单片机抢答器proteus仿真设计

一、系统方案 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 void timer0_init() //定时器初始化 { TCCR00x07; //普通模式,OC0不输出,1024分频 TCNT0f_count; //初值,定时为10ms TIFR0x01; //清中断标志…

【单片机】UART、I2C、SPI、TTL、RS232、RS422、RS485、CAN、USB、SD卡、1-WIRE、Ethernet等常见通信方式

在单片机开发中,UART、I2C、RS485等普遍在用,这里做一个简单的介绍 UART通用异步收发器 UART口指的是一种物理接口形式(硬件)。 UART是异步(指不使用时钟同步,依靠帧长进行判断),全双工(收发…

比较器的工作原理及性能指标介绍

一、什么是比较器 比较器的功能是比较两个或更多数据项,以确定它们是否相等,或者确定它们之间的大小关系和排列顺序,这称为比较。可以实现此比较功能的电路或设备称为比较器。比较器是将模拟电压信号与参考电压进行比较的电路。比较器的两个…

DHCP(自动获取IP地址技术)第六课

一 DHCP的概念 DHCP (Dynamic Host Configuration Protocol) 是一种自动分配IP地址和其他网络配置的网络协议。它允许设备在加入网络时自动获取所需的网络配置,如IP地址、子网掩码、默认网关、DNS服务器等。 DHCP通过中央服务器(DHCP服务器&#xff09…

嵌套的列表推导式(可以转置行列)学习

代码练习 list1[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15] ] print(list1) result1[[list2[i] for list2 in list1] for i in range(len(list1[0]))] print(result1) result2[[list3[i] for list3 in result1] for i in range(len(result1[0]))] print(result2) zip-test pr…

TFTLCD液晶屏图标的显示

前言 (1)本系列是基于STM32的项目笔记,内容涵盖了STM32各种外设的使用,由浅入深。 (2)小编使用的单片机是STM32F105RCT6,项目笔记基于小编的实际项目,但是博客中的内容适用于各种单片…

视频智能分析平台EasyCVR安防视频汇聚平台助力森林公园防火安全的应用方案

一、研发背景 随着经济的发展和人们生活水平的提高,越来越多的人喜欢在周末去周边的森林公园旅游,享受大自然的美景,并进行野炊和烧烤等娱乐活动。然而,近年来由于烟蒂和烧烤碳渣等人为因素,森林公园火灾频繁发生。森…

Acwing796.子矩阵的和

理解二维前缀和&#xff1a; #include <iostream>using namespace std;const int N 1010;int a[N][N], s[N][N];int main() {int n, m, q;cin >> n >> m >> q;for (int i 1; i < n; i)for (int j 1; j < m; j) {scanf("%d", &a…

ChatGPT Enterprise:AI 助手的商业化之路

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

C++笔记之单例通过GetInstance传递参数

C笔记之单例通过GetInstance传递参数 code review! 文章目录 C笔记之单例通过GetInstance传递参数例1.普通指针的单例例2.结合智能指针和std::call_once例3.编译不通过的错误例子&#xff0c;在GetInstance内不可以使用std::make_shared来创建对象 例1.普通指针的单例 运行 …