Python代码中的捕捉性能-CPU分析(解释器)
来源:互联网 发布:电大c语言考核册答案 编辑:程序博客网 时间:2024/04/29 05:54
在这篇文章中,我将介绍一些工具和方法,可以在运行Python脚本时对剖析器进行剖析。
就像在我们之前的文章中一样,CPU分析的含义是一样的,但是现在我们不是针对Python脚本的。相反,我们想知道Python解释器是如何工作的,以及在运行我们的Python脚本时花费多少时间。
接下来我们将看到如何跟踪CPU使用情况,并找到解释器中的热点。
系列索引
一旦帖子发布,下面的链接将会生效:
- 建立
- 内存分析
- CPU分析 - Python脚本
- CPU分析 - Python解释器
测量CPU使用率
对于这篇文章,我将主要使用与内存分析和脚本CPU使用相同的脚本,您可以在下面或在这里看到它。
import timedef primes(n): if n == 2: return [2] elif n < 2: return [] s = [] for i in range(3, n+1): if i % 2 != 0: s.append(i) mroot = n ** 0.5 half = (n + 1) / 2 - 1 i = 0 m = 3 while m <= mroot: if s[i]: j = (m * m - 3) / 2 s[j] = 0 while j < half: s[j] = 0 j += m i = i + 1 m = 2 * i + 3 l = [2] for x in s: if x: l.append(x) return ldef benchmark(): start = time.time() for _ in xrange(40): count = len(primes(1000000)) end = time.time() print "Benchmark duration: %r seconds" % (end-start)benchmark()
优化后的版本是bellow或here:
import timedef primes(n): if n==2: return [2] elif n<2: return [] s=range(3,n+1,2) mroot = n ** 0.5 half=(n+1)/2-1 i=0 m=3 while m <= mroot: if s[i]: j=(m*m-3)/2 s[j]=0 while j<half: s[j]=0 j+=m i=i+1 m=2*i+3 return [2]+[x for x in s if x]def benchmark(): start = time.time() for _ in xrange(40): count = len(primes(1000000)) end = time.time() print "Benchmark duration: %r seconds" % (end-start)benchmark()
CPython
CPython是多功能的,完全用C编写,因此更容易测量和/或配置文件。您可以在这里找到在GitHub上托管的CPython的源代码。默认情况下,你会看到最新的分支,在写这个的时候是3.7+,但是所有其他的分支都可以下到2.7。
在我们的帖子中,我们将重点介绍CPython 2,但同样的步骤可以成功应用到最新的3版本。
代码覆盖工具
查看正在运行的C代码部分的最简单方法之一是使用代码覆盖率工具。
我们首先克隆回购:
git clone https://github.com/python/cpython /cd cpython
git checkout 2.7
./configure
复制目录中的脚本并运行以下命令:
make coverage
./python 04.primes-v1.py
make coverage-lcov
第一行将编译GCOV支持的解释器,第二行将运行工作负载并收集.gcda文件中的分析数据,第三行解析包含分析数据的文件,并在名为的文件夹中创建一堆HTML文件lcov-report
。
如果我们index.html
在浏览器中打开,我们可以看到解释器源代码中被执行的位置来运行我们的Python脚本。你会看到像下面的东西:
在顶层,我们可以看到构成源代码的每个目录以及覆盖的代码量。例如,我们打开Objects
目录, listobject.c.gcov.html
文件。虽然我们不会完全解读,但我们分析一部分。看下面的部分。
如何阅读?在黄色的列上,你可以看到来自C文件代码的行号。在下一列中,您可以看到特定行被执行的次数。在最右边的列中,您可以看到实际的C源代码。
在这个例子中,这个方法listiter_next
被称为6000万次。
我们是如何得到这个功能的?如果我们仔细看看我们的Python脚本,我们观察到它使用了很多列表迭代并追加。(另一点可以导致脚本优化首先)
让我们继续其他一些专用工具。
PERF
有关更多信息,我们可以使用perf
Linux系统上提供的工具。官方文档可以在这里阅读。
我们(重新)使用以下内容构建CPython解释器。如果你没有在同一个目录中下载Python脚本,你应该这样做。另外,请确保perf
已安装在您的系统上。
./configure --with-pydebug
make
运行perf
如下。Brendan Gregg写的这个优秀的页面可以看到更多的使用perf的方法。
sudo perf record ./python 04.primes-v1.py
运行脚本之后,您将看到如下所示的内容:
Benchmark duration: 32.03910684585571 seconds
[21868 refs]
perf record: Woken up 20 times to write data ]
[ perf record: Captured and wrote 4.914 MB perf.data (125364 samples) ]
要查看结果,运行`sudo perf report` 以获得度量。
只有最有趣的电话才能被保存。在上面的屏幕中,我们看到花费的时间最多PyEval_EvalFrameEx
。这是主要的解释器循环,我们对这个例子不感兴趣。相反,我们感兴趣的是下一个耗时的功能 - listiter_next
占用10.70%的时间。
运行优化版本后,我们看到以下内容:
经过我们的优化,该listiter_next
功能只消耗了2.11%的时间。读者可以根据口译员的情况做进一步的优化。
Valgrind的/ Callgrind
另一个可以用来查找瓶颈的工具是Valgrind,它的一个叫做callgrind的插件。更多细节可以在这里阅读。
如果尚未完成,我们(重新)使用以下内容构建CPython解释器。如果你没有在同一个目录中下载Python脚本,你应该这样做。另外,请确保valgrind
已安装在您的系统上。
./configure --with-pydebug
make
运行valgrind
如下:
valgrind --tool=callgrind --dump-instr=yes \
--collect-jumps=yes --collect-systime=yes \
--callgrind-out-file=callgrind-%p.out -- ./python 04.primes-v1.py
结果是:
Benchmark duration: 1109.4096319675446 seconds
[21868 refs]
==24152==
==24152== Events : Ir sysCount sysTime
==24152== Collected : 115949791666 942 208
==24152==
==24152== I refs: 115,949,791,666
为了可视化,我们将使用KCacheGrind。
kcachegrind callgrind-2327.out
PyPy
在PyPy上,可以成功使用的配置文件是非常有限的,恢复到vmprof,一个由开发PyPy的人写的工具。
首先,从这里下载PyPy 。在此之后,启用pip
对它的支持
安装vmprof
很简单,只需运行:
bin/pypy -m pip install vmprof
运行工作量为:
bin/pypy -m vmprof --web 04.primes-v1.py
并在浏览器中打开控制台中显示的链接(以http://vmprof.com/#/开头 )
作者:Alecsandru Patrascu,alecsandru.patrascu [at] rinftech [dot] com
原文:https://pythonfiles.wordpress.com/2017/08/24/hunting-performance-in-python-code-part-4/
- Python代码中的捕捉性能-CPU分析(解释器)
- Python代码中的捕捉性能-CPU分析(Python脚本)
- Python代码中的捕捉性能-内存分析
- Python代码中捕捉性能-环境设置
- Oracle数据库CPU超高问题分析捕捉
- 波形捕捉:(3)"捕捉设备"性能
- cpu性能测试代码
- cpu性能消耗分析
- 性能调试--CPU性能分析
- python几个实际代码的性能分析
- lr:项目 性能测试中的数据解释与分析
- 代码捕捉iOS开发中的程序异常
- 获取CPU性能信息代码
- linux-性能分析之cpu
- Python 装饰器捕捉异常
- 性能调试---(三)CPU性能分析
- 性能调试---(三)CPU性能分析
- #python中的汉诺塔递归算法代码分析
- 单进程单线程,完成并发服务器(select版)
- Java线程休眠Thread.sleep()(2)
- DB2排查错误小技巧
- How to Learn Programming Without an Internet?
- 逻辑英语_名词从句
- Python代码中的捕捉性能-CPU分析(解释器)
- Ngnix详细安装部署教程
- 改造 Android 官方架构组件 ViewModel
- 假设以两个元素依值递增有序排列的线性表A和B分别表示两个集合,现要求另辟空间构成一个顺序链表C
- 20171214普及组测试题解与反思1、3
- mybatis执行insert语句,如何返回主键给对象的问题(限主键为整数类型)
- Servlet 工作原理解析(个人标记,重点,随时复习)
- UIView 监听某一个属性的变化
- studio 设置护眼色背景色