《Python高性能编程》——第2章 通过性能分析找到瓶颈 2.1 高效地分析性能

第2章 通过性能分析找到瓶颈

读完本章之后你将能够回答下列问题

  • 如何找到代码中速度和RAM的瓶颈?
  • 如何分析CPU和内存使用情况?
  • 我应该分析到什么深度?
  • 如何分析一个长期运行的应用程序?
  • 在CPython台面下发生了什么?
  • 如何在调整性能的同时确保功能的正确?

性能分析帮助我们找到瓶颈,让我们在性能调优方面做到事半功倍。性能调优包括在速度上巨大的提升以及减少资源的占用,也就是说让你的代码能够跑得“足够快”以及“足够瘦”。性能分析能够让你用最小的代价做出最实用的决定。

任何可以测量的资源都可以被分析(不仅是CPU!)。我们在本章将分析CPU的时间和内存的占用。你也可以将同样的技术用于分析网络带宽和磁盘I/O。

如果一个程序跑得太慢或占用了太多RAM,那么你一定希望把有问题的代码修正。当然,你完全可以跳过性能分析,修正你认为可能有问题的地方——但是小心,你很有可能“修正了”错误的地方。比起依靠你的直觉,更有效率的做法是先进行性能分析,做出一个假设,然后再改动你的代码结构。

人有时候懒点比较好。先进行性能分析让你能够迅速定位需要被解决的瓶颈,然后你就可以用最小的改动获得你需要的性能提升。如果你回避性能分析直接进行优化,那么你很有可能最终付出了更多的努力。优化应该总是基于性能分析的结果。

2.1 高效地分析性能

性能分析的首要目标是对受测系统进行测试来发现哪里太慢(或占用太多RAM,或导致太多磁盘I/O或网络I/O)。性能分析一般会导致额外的性能开销(一般会慢10到100倍),但你依然希望你的代码尽可能像是在真正的环境中一样运行。所以要以测试用例的方式将你需要测试的那部分系统独立出来。最好这个测试用例已经使用了一套自己的模块。

本章介绍的第一个基本技术包括IPython的%timeit魔法函数,time.time(),以及一个计时修饰器。你可以使用这些技术来了解语句和函数的行为。

然后我们会学习cProfile(2.6节),告诉你如何使用这个内建工具来了解代码中哪些函数耗时最长。这将让你站在高处俯瞰你的问题,使你能够将注意力集中到关键函数上。

接下来,我们会去看line_profiler(2.8节),这个工具能够对你选定的函数进行逐行分析。其结果将包含每行被调用的次数以及每行花费的时间百分比。这恰能让你知道是哪里跑得慢以及为什么。

有了line_profiler的结果,你就有了足够的信息去使用编译器(第7章)。

在第6章(例6-8),你将学到如何使用perf stat命令来了解最终执行于CPU上的指令的个数以及CPU缓存的利用率。这让你能够进一步调优矩阵操作。读完本章后你应该去看看那个例子。

line_profiler之后,我们会演示heapy(2.10节),它可以追踪Python内存中所有的对象——这对于消灭奇怪的内存泄漏特别有用。如果你的系统需要持续运行,那么你会对dowser(2.11节)感兴趣,它让你能够通过一个Web浏览器界面审查一个持续运行的进程中的实时对象。

为了帮助你了解为什么你的RAM占用特别高,我们会给你演示memory_profiler(2.9节)。它能以图的形式展示RAM的使用情况随时间的变化,这样你就可以向你的同事们解释为什么某个函数占用了比预期更多的RAM。

 备忘 

无论你用什么方法分析代码性能,都必须记得用足够的单元测试覆盖你的代码。单元测试能帮助你避免愚蠢的错误并让你的结果可重现。没有单元测试风险极大。

在编译或重写你的算法之前始终进行性能分析。你需要证据来决定最有效的优化手段。

最后,我们还会给你介绍CPython中的Python字节码(2.12节),这样你就能够了解在其台面下发生了什么。具体来说,了解基于栈的Python虚拟机如何运行将帮助你明白为什么某个编程风格会跑得比别人慢。

在结束本章之前,我们会回顾如何在性能分析中集成单元测试(2.13节),让代码跑得更有效的同时维持正确。

最后我们将讨论性能分析的策略(2.14节),这样你就能够可靠地分析你的代码并收集正确的数据来验证你的假设。在这里,你将了解到动态CPU频率以及TurboBoost等特性能够如何歪曲你的性能分析结果以及如何禁用这些功能。

为了讲解所有这些步骤,我们需要以一个便于分析的函数为例。下一节我们介绍Julia集合。这是一个对RAM有一点饥渴的CPU密集型函数,而且它还具有非线性的行为(这样我们就无法轻易预测其结果),这意味着我们需要在运行时分析其性能而没法进行线下调查。

时间: 2025-01-21 07:48:56

《Python高性能编程》——第2章 通过性能分析找到瓶颈 2.1 高效地分析性能的相关文章

《Python高性能编程》——导读

前 言 Python很容易学.你之所以阅读本书可能是因为你的代码现在能够正确运行,而你希望它能跑得更快.你可以很轻松地修改代码,反复地实现你的想法,你对这一点很满意.但能够轻松实现和代码跑得够快之间的取舍却是一个世人皆知且令人惋惜的现象.而这个问题其实是可以解决的. 有些人想要让顺序执行的过程跑得更快.有些人需要利用多核架构.集群,或者图形处理单元的优势来解决他们的问题.有些人需要可伸缩系统在保证可靠性的前提下酌情或根据资金多少处理更多或更少的工作.有些人意识到他们的编程技巧,通常是来自其他语言

《Python高性能编程》——第1章 理解高性能Python 1.1 基本的计算机系统

第1章 理解高性能Python 读完本章之后你将能够回答下列问题 计算机架构有哪些元素? 常见的计算机架构有哪些? 计算机架构在Python中的抽象表达是什么? 实现高性能Python代码的障碍在哪里? 性能问题有哪些种类? 计算机编程可以被认为是以特定的方式进行数据的移动和转换来得到某种结果.然而这些操作有时间上的开销.因此,高性能编程可以被认为是通过降低开销(比如撰写更高效的代码)或改变操作方式(比如寻找一种更合适的算法)来让这些操作的代价最小化. 数据的移动发生在实际的硬件上,我们可以通过

《Python高性能编程》——1.2 将基本的元素组装到一起

1.2 将基本的元素组装到一起 仅理解计算机的基本组成部分并不足以理解高性能编程的问题.所有这些组件的互动与合作还会引入新的复杂度.本段将研究一些样本问题,描述理想的解决方案以及Python如何实现它们. 警告:本段可能看上去让人绝望--大多数问题似乎都证明Python并不适合解决性能问题.这不是真的,原因有两点.首先,在所有这些"高性能计算要素"中,我们忽视了一个至关重要的要素:开发者.原生Python在性能上欠缺的功能会被迅速开发出来.另外,我们会在本书中介绍各种模块和原理来帮助减

《Python高性能编程》——2.6 使用cProfile模块

2.6 使用cProfile模块 cProfile是一个标准库内建的分析工具.它钩入CPython的虚拟机来测量其每一个函数运行所花费的时间.这一技术会引入一个巨大的开销,但你会获得更多的信息.有时这些额外的信息会给你的代码带来令人惊讶的发现. cProfile是标准库内建的三个分析工具之一,另外两个是hotshot和profile.hotshot还处于实验阶段,profile则是原始的纯Python分析器.cProfile具有跟profile一样的接口,且是默认的分析工具.如果你对这些库的历史

《Python高性能编程》——2.14 确保性能分析成功的策略

2.14 确保性能分析成功的策略 性能分析需要一些时间和精力.如果你把需要测试的代码段跟你代码的主体分离,你会有一个更好的机会去了解你的代码.然后你可以用单元测试来保证正确性,你还可以传入精心编造的真实数据来测试算法的有效性. 记得关闭任何基于BIOS的加速器,因为它们只会混淆你的结果.Ian的笔记本电脑使用的Intel TurboBoost功能可以在温度足够低的时候将CPU暂时加至极速.这意味着低温时运行同一段代码的速度可能比高温时要快.你的操作系统也许还控制了时钟的速度--使用电池电源的笔记

《Python高性能编程》——1.3 为什么使用Python

1.3 为什么使用Python Python具有高度的表现力且容易上手--新开发者会很快发现他们可以在很短时间里做到很多.许多Python库包含了用其他语言编写的工具,使Python可以轻易调用其他系统.比如,scikit-learn机器学习系统包含了LIBLINEAR和LIBSVM(两者皆以C语言写成),numpy库则包含了BLAS以及其他用C和Fortran语言写的库.因此,正确运用这些库的Python代码确实可以在速度上做到跟C媲美. Python被誉为"内含电池",因为它内建了

Python树莓派编程第3章

第3章 Python介绍 你可能还记得我们在第1章中提到,制作树莓派的初衷是为了让每个人(尤其是孩子们)都拥有编程的环境.为了实现该目的,树莓派的创造者们想要推出一台价格相对便宜但性能十分强劲的计算机,每个人都可以将这台计算机连接至键盘.鼠标.显示器进行编程. 创造树莓派的另一个原因是希望简化编程.为此,Eben Upton和他的同伴决定将Python语言集成到树莓派的操作系统中.他们认为,Python是一种强大的编程语言,那些没有编程经验的人也可以轻松快速地学会. 在本章,我将对Python进

《Python高性能编程》——2.8 用line_profiler进行逐行分析

2.8 用line_profiler进行逐行分析 根据Ian的观点,Robert Kern的line_profiler是调查Python的CPU密集型性能问题最强大的工具.它可以对函数进行逐行分析,你应该先用cProfile找到需要分析的函数,然后用line_profiler对函数进行分析. 当你修改你的代码时,值得打印出这个工具的输出以及代码的版本,这样你就拥有一个代码变化(无论有没有用)的记录,让你可以随时查阅.当你在进行逐行改变时,不要依赖你的记忆. 输入命令pip install lin

《Python高性能编程》——2.3 计算完整的Julia集合

2.3 计算完整的Julia集合 我们在本节分解Julia集合的生成代码.我们将在本章以各种方法分析它.如例2-1所示,在模块的一开始,我们导入time模块作为我们的第一种分析手段并定义一些坐标常量. 例2-1 定义空间坐标的全局常量 """Julia set generator without optional PIL-based image drawing""" import time # area of complex space to i