Scalene 是一个 Python 的高性能 CPU 和 内存分析器,它可以做到很多其他Python分析器不能做到的事情。它在能提供更多详细信息的同时,比其他的分析器要快几个数量级。
numpy
数组转化成了Python数组,反之亦然)。Scalene 通过 pip 包的形式进行分发,可以运行在Mac OS X和Linux平台(包括在Windows WSL2中运行的Ubuntu)。
你可以通过下面的方式安装:
% pip install scalene
或者
% python -m pip install scalene
注意: 现在这样安装Scalene,是不会安装内存分析的库,所以你只能用它来执行CPU的分析。如果要使用它的内存分析能力,你需要下载这个代码仓库。
NEW: 你现在可以通过以下命令,在 Mac OS X 上使用 brew 安装内存分析的部分:
% brew tap emeryberger/scalene
% brew install --head libscalene
这将会安装一个你可以使用的 scalene
脚本(下面会提到)。
下面的命令会让 Scalene 在提供的示例程序上执行 行级别的CPU分析。
% scalene test/testme.py
如果你使用Homebrew安装 Scalene 库,你只需要执行 scalene
就可以执行行级别的CPU和内存分析:
% scalene test/testme.py
否则,你需要运行 make
来先构建一个指定的内存分配器:
% make
在 Mac OS X 系统上进行分析(不使用Homebrew安装):
% DYLD_INSERT_LIBRARIES=$PWD/libscalene.dylib PYTHONMALLOC=malloc scalene test/testme.py
在Linux系统上分析:
% LD_PRELOAD=$PWD/libscalene.so PYTHONMALLOC=malloc scalene test/testme.py
执行时增加 --help
来查看全部配置:
% scalene --help
usage: scalene [-h] [-o OUTFILE] [--profile-interval PROFILE_INTERVAL]
[--wallclock]
prog
Scalene: a high-precision CPU and memory profiler.
https://github.com/emeryberger/Scalene
for CPU profiling only:
% scalene yourprogram.py
for CPU and memory profiling (Mac OS X):
% DYLD_INSERT_LIBRARIES=$PWD/libscalene.dylib PYTHONMALLOC=malloc scalene yourprogram.py
for CPU and memory profiling (Linux):
% LD_PRELOAD=$PWD/libscalene.so PYTHONMALLOC=malloc scalene yourprogram.py
positional arguments:
prog program to be profiled
optional arguments:
-h, --help show this help message and exit
-o OUTFILE, --outfile OUTFILE
file to hold profiler output (default: stdout)
--profile-interval PROFILE_INTERVAL
output profiles every so many seconds.
--wallclock use wall clock time (default: virtual time)
下面的表格把 scalene 和不同分析器的性能做了比较。运行的示例程序 (benchmarks/julia1_nopil.py
) 来自于 Gorelick 和 Ozsvald 的 《高性能Python编程》。所有的这些结果都是在 2016款 MacBook Pro上运行的。
Profiler | Time | Slowdown |
---|---|---|
original program | 6.71s | 1.0x |
cProfile | 11.04s | 1.65x |
Profile | 202.26s | 30.14x |
pyinstrument | 9.83s | 1.46x |
line_profiler | 78.0s | 11.62x |
pprofile (deterministic) | 403.67s | 60.16x |
pprofile (statistical) | 7.47s | 1.11x |
yappi (CPU) | 127.53s | 19.01x |
yappi (wallclock) | 21.45s | 3.2x |
py-spy | 7.25s | 1.08x |
memory_profiler | > 2 hours | >1000x |
scalene (CPU only) | 6.98s | 1.04x |
scalene (CPU + memory) | 7.68s | 1.14x |
这个表格是其他分析器 vs. Scalene 的功能比较。
Profiler | Line-level? | CPU? | Wall clock vs. CPU time? | Python vs. native? | Memory? | Unmodified code? | Threads? |
---|---|---|---|---|---|---|---|
cProfile | ✔ | wall clock | ✔ | ||||
Profile | ✔ | CPU time | ✔ | ||||
pyinstrument | ✔ | wall clock | ✔ | ||||
line_profiler | ✔ | ✔ | wall clock | ||||
pprofile (deterministic) | ✔ | ✔ | wall clock | ✔ | ✔ | ||
pprofile (statistical) | ✔ | ✔ | wall clock | ✔ | ✔ | ||
yappi (CPU) | ✔ | CPU time | ✔ | ✔ | |||
yappi (wallclock) | ✔ | wall clock | ✔ | ✔ | |||
py-spy | ✔ | ✔ | both | ✔ | ✔ | ||
memory_profiler | ✔ | ✔ | |||||
scalene (CPU only) | ✔ | ✔ | both | ✔ | ✔ | ✔ | |
scalene (CPU + memory) | ✔ | ✔ | both | ✔ | ✔ | ✔ | ✔ |
Scalene 打印被分析程序中带注释的源代码,以及程序在同目录和子目录使用到的任何模块。下面是一个来自 pystone.py pystone.py
的片段,只使用了CPU分析:
benchmarks/pystone.py: % of CPU time = 100.00% out of 3.66s.
| CPU % | CPU % |
Line | (Python) | (native) | [benchmarks/pystone.py]
--------------------------------------------------------------------------------
[... lines omitted ...]
137 | 0.27% | 0.14% | def Proc1(PtrParIn):
138 | 1.37% | 0.11% | PtrParIn.PtrComp = NextRecord = PtrGlb.copy()
139 | 0.27% | 0.22% | PtrParIn.IntComp = 5
140 | 1.37% | 0.77% | NextRecord.IntComp = PtrParIn.IntComp
141 | 2.47% | 0.93% | NextRecord.PtrComp = PtrParIn.PtrComp
142 | 1.92% | 0.78% | NextRecord.PtrComp = Proc3(NextRecord.PtrComp)
143 | 0.27% | 0.17% | if NextRecord.Discr == Ident1:
144 | 0.82% | 0.30% | NextRecord.IntComp = 6
145 | 2.19% | 0.79% | NextRecord.EnumComp = Proc6(PtrParIn.EnumComp)
146 | 1.10% | 0.39% | NextRecord.PtrComp = PtrGlb.PtrComp
147 | 0.82% | 0.06% | NextRecord.IntComp = Proc7(NextRecord.IntComp, 10)
148 | | | else:
149 | | | PtrParIn = NextRecord.copy()
150 | 0.82% | 0.32% | NextRecord.PtrComp = None
151 | | | return PtrParIn
下面是一个启用了内存分析的示例,运行的是Julia的基准测试。第一行是一个“sparkline”,总结了一段时间内的内存消耗。
Memory usage: ▁▁▄▇█▇▇▇█▇█▇█▇█▇█▇▇▇▇█▇▇█▇█▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇█ (max: 105.73MB)
benchmarks/julia1_nopil.py: % of CPU time = 100.00% out of 9.11s.
| CPU % | CPU % | Avg memory | Memory |
Line | (Python) | (native) | growth (MB) | usage (%) | [benchmarks/julia1_nopil.py]
--------------------------------------------------------------------------------
1 | | | | | import sys
[... lines omitted ...]
30 | | | | | def calculate_z_serial_purepython(maxiter, zs, cs):
31 | | | | | """Calculate output list using Julia update rule"""
32 | | | 18 | 0.74% | output = [0] * len(zs)
33 | 0.44% | 0.06% | 16 | 1.32% | for i in range(len(zs)):
34 | | | | | n = 0
35 | 0.22% | 0.04% | -16 | | z = zs[i]
36 | 0.22% | 0.07% | | | c = cs[i]
37 | 26.12% | 5.57% | | | while abs(z) < 2 and n < maxiter:
38 | 36.04% | 7.74% | 16 | 85.09% | z = z * z + c
39 | 12.01% | 2.70% | -16 | 3.96% | n += 1
40 | 0.33% | 0.10% | | | output[i] = n
41 | | | | | return output
42 | | | | |
正的内存数代表内存的分配量(以MB为单位),负的内存数代表内存的回收量。 内存的使用率代表特定行中总内存分配的活动。
欢迎大家分享哦~
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。