什么决定了调试器的运行时性能

时间:2012-02-19 04:14:52

标签: python performance debugging python-3.x

我尝试使用Wing IDE(v.4.1.3)和Komodo IDE(v.7.0.0)调试Python 3。因为,预计调试器会增加大量的运行时开销。但让我感到惊讶的是,调试器之间的差异是多么不同。

以下是同一程序的运行时间。没有断点或其他任何东西,只是没有任何实际调试的常规运行:

  • 由python解释器执行:26秒
  • 由调试器#1执行:137秒
  • 由调试器#2执行:1143秒

我将调试器称为匿名#1和#2,以免这成为其中一个的无意(并可能被误导)广告。

其中一个调试器真的是“快”的8倍吗?

还是有一些设计权衡,更快的调试器放弃一些功能,或精度,或鲁棒性,或其他什么,以换取更快的速度?如果是这样的话,我很想知道这些细节,无论是专门用于Wing / Komodo还是Python调试器。

2 个答案:

答案 0 :(得分:14)

做一个优化的Python调试器就像任何其他软件一样:性能上可能会有所不同(我是PyDev作者,我已经完成了PyDev调试器,因此,我可以对它进行评论,但不能在其他,所以,我只是解释一下优化Python调试器 - 因为我花了很多时间优化PyDev调试器 - 我不会真正谈论其他实现,因为我不知道它们是怎样的已经完成 - 除了pdb,但pdb在遇到断点并且你正在逐步执行它之后实际上并不是一个快速的调试器实现,尽管在你实际执行将开始跟踪的代码之前运行未完成的东西它确实运行良好你的代码)。

特别是,任何'天真'调试器只需在每个帧中启用Python跟踪并检查执行的每一行是否存在断点匹配,就可以使程序慢得多(这大致是pdb的工作方式:无论何时输入上下文将跟踪它并且对于每一行调用它将检查断点是否与它匹配,因此,我相信任何期望快速的实现都不能真正依赖它。)

我知道PyDev调试器有几个优化...主要的一个是:当调试器进入一个新帧(即:function)时,它会检查是否有任何'潜在的'断点可能会被击中,如果没有,它甚至不会跟踪该功能(另一方面,当程序执行后稍后添加断点时,它必须去重新评估所有先前的假设,因为任何当前帧都可能最终跳过一个断点)。如果它确定应该跟踪某个帧,它将为该帧创建一个新实例,该实例将负责缓存与该帧相关的所有内容(这只能从Python 2.5中实现,因此,在使用Python 2.4时而且,除非安装了threadframe扩展,否则调试器将尝试模拟它,这将使Python 2.4上的速度相当慢。

另外,PyDev调试器目前利用了Cython,即使这只限于CPython ...... Jython,IronPython和PyPy也没有利用它),因此,考虑到纯Python模式,许多优化仍然完成(幸运的是,Cython与Python非常接近,因此需要进行一些更改才能使其在使用Cython的CPython上更快地运行。)

有关PyDev调试器优化演变的一些相关帖子:

http://pydev.blogspot.co.id/2017/03/pydev-560-released-faster-debugger.html

http://pydev.blogspot.co.id/2016/01/pydev-451-debug-faster.html

http://pydev.blogspot.com/2008/02/pydev-debugger-and-psyco-speedups.html

http://pydev.blogspot.com/2005/10/high-speed-debugger.html

无论如何,运行调试器总是会增加一些开销(即使经过大量优化,比如PyDev调试器),因此,PyDev也提供了可以在pdb中使用的相同方法:在代码中添加断点并且它'只会在那一点开始跟踪(这是PyDev的远程调试器功能):http://pydev.org/manual_adv_remote_debugger.html

根据您希望调试器支持的功能,它也可能更慢(例如:当您在PyDev中为捕获的异常启用中断时,程序将执行得更慢,因为它需要按顺序跟踪更多内容适当地打破。)

答案 1 :(得分:2)

这就像问为什么程序A比程序B更快。原因可能不是特定于调试领域。

我认为大多数图形调试器都构建在python标准库中提供的pdb模块的顶部或前端(尽管不是全部)。性能差异主要归结为实现细节和GUI更新开销。差异可能就像在代码的某个层中执行不必要的深拷贝与直接引用一样简单。

如果您担心调试器性能,那么您应该坚持使用速度更快的图形调试器,除非它不满足您需要的某些功能。你要求的是功能差异;既然如此,那么它们显然是最符合您需求的。

如果一个调试器正在失去精度或牺牲稳健性,那么我会立即对其进行折扣考虑。我猜测较慢的一个是:

  • 进行额外的工作或不必要的检查(如果开发人员不信任代码的其他部分,或者它们在架构上太多层或冗余)。

  • 使用一些缓存不友好或浪费的表示,或者没有像快速调试器那样在算法上调整或优化代码。正确的数据结构选择和算法优化可以产生差异的数量级。使用低级优化(如ctypes,psyco,pyrex)等。你可以产生另一个数量级的差异。请记住,python为您提供灵活且功能强大的默认容器,您始终可以“付费”#34;因为,即使你不需要他们所有的功能。

我发现WinPDB相当轻量级,并且是我经常使用的那个,因为它不会将我绑定到IDE,并且非常有效地支持远程调试。您可能还想尝试使用pydev进行日食。我刚刚开始玩的另一个新的是Python Tools for Visual Studio,看起来非常有前景。 python wiki上还有一个list of python debuggers。可能值得尝试其他人。

至于为什么一个比另一个快,有很多可能的因素。如果您可以访问调试器的源,则可以对调试器本身进行概要分析以识别性能瓶颈。但是,如果您只是想要一个能够处理所有基本用例的快速调试器,那么只需尝试一些,并坚持使用最快的服务器。