如果你觉得一个运行中的Python程序有问题,例如它的耗时比你预想的要长很多,那么你可能会想知道它到底在“干什么”,有很多方法可以实现这个目的,但是很多都是需要修改Python代码来配合的,这显然是让人最不爽的方式。
而 py-spy 这个工具提供了一种无侵入的方式来达成这个目的:
py-spy是Python程序的采样分析器。 它使你可以直观地看到Python程序花费的时间,而无需重新启动程序或以任何方式修改代码。 py-spy的开销非常低:为了提高速度,它是用Rust编写的,并且它与被分析的Python程序不在同一进程中运行。 这意味着py-spy可以安全地用于生产环境的Python代码。
py-spy 的工作原理:在Linux上使用process_vm_readv系统调用,在OSX上使用vm_read,在Windows上使用ReadProcessMemory来直接读取Python程序的内存。
下面就来看看怎么把 py-spy 用起来。
环境:Ubuntu 16.04 LTS,Python 3.6.9
▶ 安装 py-spy
最简单的方法是用 pip 安装:
pip install py-spy
但对我来说,我是在Anaconda环境下使用Python,所以我不想这样干。Anaconda cloud上面没有Linux版的 py-spy,于是我最省力的办法,就是用Rust的包管理工具 Cargo 来安装 py-spy 了。
文章来源:https://www.codelast.com/
首先安装Rust:
curl https://sh.rustup.rs -sSf | bash
这样 Rust 就被安装到了当前用户的 .cargo 目录下。
再修改 .bashrc,把Cargo添加到PATH中:
export RUST_HOME=/home/codelast/.cargo
export PATH=$RUST_HOME/bin:$PATH
现在事情就变得无比简单了,安装 py-spy:
cargo install py-spy
如果执行这个命令出错,提示:
error: linking with `cc` failed: exit code: 1|(...中间省略...)= note: /usr/bin/ld: cannot find -lunwind/usr/bin/ld: cannot find -lunwind-ptrace/usr/bin/ld: cannot find -lunwind-x86_64collect2: error: ld returned 1 exit statuserror: aborting due to previous errorerror: failed to compile `py-spy v0.3.0`, intermediate artifacts can be found at `/tmp/cargo-installZWBhFq`Caused by:could not compile `py-spy`.
sudo apt install libunwind-dev
py-spy top --pid 1780
Permission Denied: Try running again with elevated permissions by going 'sudo env "PATH=$PATH" !!'
sudo env "PATH=$PATH" !!
现在你会看到类似于 Linux top 命令的输出:
你可以从中找到每个函数的执行时间。
文章来源:https://www.codelast.com/
或者你想要酷炫一点的结果,可以生成火焰图:
py-spy record -o profile.svg --pid 1780
图片从上到下,标识了函数调用栈,X轴则表示函数的执行时间长短(颜色深浅不代表任何问题),越长的,表明该函数执行时间越长,这对性能分析很有用。
文章来源:https://www.codelast.com/
而且更酷的是,如果你把生成的 svg 图片拉到一个浏览器窗口里查看,会发现它是“可点击”的,如果你把鼠标悬停在图片上,就会看到像上图一样的 tip 提示,在左下角还会显示出有当前鼠标指向的这个函数的统计信息,如果你不是悬停,而是点击这个函数所在的矩形区域,则会放大这个函数其下的区域,像极了一个可以导航的网页:
在放大状态下,点击左上角的“Reset Zoom”就可以回到初始的未缩放状态。是不是很爽!
py-spy 还有更多强大功能,请到其主页去进一步探索。
文章来源:https://www.codelast.com/
➤➤ 版权声明 ➤➤
转载需注明出处:codelast.com
感谢关注我的微信公众号(微信扫一扫):