What determines debugger run-time performance - python

I have tried debugging Python 3 with Wing IDE (v.4.1.3) and Komodo IDE (v.7.0.0). As, expected the debugger adds a lot of run-time overhead. But what surprised me is how different the debuggers can be between each other.
Here are the run-times for the same program. No breakpoints or anything else, just a regular run without any actual debugging:
executed by python interpreter: 26 sec
executed by debugger #1: 137 sec
executed by debugger #2: 1143 sec
I refer to the debuggers as anonymous #1 and #2 lest this becomes an unintentional (and possibly misguided) advertising for one of them.
Is one of the debuggers really 8 times "faster"?
Or is there some design trade-off, where a faster debugger gives up some features, or precision, or robustness, or whatever, in return for greater speed? If so, I'd love to know those details, whether for Wing/Komodo specifically, or Python debuggers in general.

Doing an optimized Python debugger is as any other software: things can be really different performance-wise (I'm the PyDev author and I've done the PyDev debugger, so, I can comment on it, but not on the others, so, I'll just explain a bit on optimizing a Python debugger -- as I've spent a lot of time optimizing the PyDev debugger -- I won't really talk about other implementations as I don't know how they were done -- except for pdb, but pdb is not really a fast debugger implementation after it hits a breakpoint and you're stepping through it, although it does work well by running things untraced until you actually execute the code that'll start tracing your code).
Particularly, any 'naive' debugger can make your program much slower just by enabling the Python trace in each frame and checking if there's a breakpoint match for each line executed (this is roughly how pdb works: whenever you enter a context it'll trace it and for each line called it'll check if a breakpoint matches it, so, I believe any implementation that expects to be fast can't really rely on it).
I know the PyDev debugger has several optimizations... the major one is the following: when the debugger enters a new frame (i.e.: function) it will check if there's any 'potential' breakpoint that may be hit there and if there's not, it won't even trace that function (on the other hand, when a breakpoint is added later on after the program is executing, it'll have to go and reevaluate all previous assumptions, as any current frame could end up skipping a breakpoint). And if it determines that some frame should be traced, it'll create a new instance for that frame which will be responsible for caching all that's related to that frame (this was only really possible from Python 2.5, so, when working on Python 2.4 and earlier, unless the threadframe extension is installed, the debugger will try to emulate that, which will make it considerably slower on Python 2.4).
Also, the PyDev debugger currently takes advantage of Cython, even though this is only restricted to CPython... Jython, IronPython and PyPy don't take advantage of it), so, many optimizations are still done considering pure Python mode (thankfully Cython is close enough to Python so that few changes are needed in order to make it work faster on CPython with Cython).
Some related posts regarding PyDev debugger optimization evolution:
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
Anyways, running with the debugger in place will always add some overhead (even when heavily optimized such as the PyDev debugger), so, PyDev also provides the same approach that may be used in pdb: add a breakpoint in code and it'll only start tracing at that point (which is the remote debugger feature of PyDev): http://pydev.org/manual_adv_remote_debugger.html
And depending on the features you want the debugger to support, it can also be slower (e.g.: when you enable the break for caught exceptions in PyDev, the program will execute slower because it'll need to trace more things in order to properly break).

This is like asking why is program A faster than program B. The reason may not be specific to the domain of debugging.
I would imagine most graphical debuggers are built on top or a frontend to the pdb module provided in the python standard library (though not all are). The performance differences would mostly boil down to implementation details and GUI updating overhead. The difference could be as simple as doing unnecessary deep copies vs direct referencing in some layer of the code.
If you are concerned about debugger performance, then you should stick with the faster graphical debugger, unless it is not satisfying some feature you need. You are asking for feature differences; since this is the case, they are both obviously current serving your needs feature-wise.
If one debugger is losing precision or sacrificing robustness, then I would discount it immediately from consideration. I would chance a guess that the slower one is either:
Doing extra work or unnecessary checks (if the developer doesn't trust other parts of the code, or their are too many layers or redundancy architecturally).
Using some cache-unfriendly or wasteful representation or hasn't tuned or optimised the code algorithmically as much as the faster debugger. Correct data structure choice and algorithmic optimisations can make orders of magnitudes of difference. Using low-level optimisations (like ctypes, psyco, pyrex) etc.. you can make another order of magnitude of a difference. Remember python gives you flexible and powerful default containers that you always "pay" for, even if you dont need all their functionality.
I have found that WinPDB is fairly lightweight, and is the one I usually use, since it doesnt tie me to an IDE, and supports remote debugging quite effectively. You might also want to try eclipse with pydev. Another new one I have just started playing around with is Python Tools for Visual Studio which looks very promising. There is also a list of python debuggers on the python wiki. It might be worth giving the others a try.
As to why one is faster than the other, there are a multitude of possible factors. If you have access to the source of the debugger, you might be able to profile the debugger itself to identify the performance bottlenecks. But if you just want a fast debugger that handles all the basic use cases, just try a few more out, and stick with the fastest that serves your needs.

Related

Why is the GHC test suite written in Python, not Haskell?

I noticed that GHC (a widely-used Haskell compiler) has a test suite written in Python, not in Haskell (as I would naively expect). What is the history of this? Are there particular advantages to writing the test suite in a different language?
edit: Per a suggestion in the comments, I asked this in /r/haskell. It has now generated three answers, which I've quoted below:
tathougies said:
The test suite driver seems to be written in Python. Python is a good high-level scripting language.
It's like asking 'why does GHC use Make instead of haskell'? Probably because make is better at running shell programs with external dependency resolution built-in.
The tests themselves seem to be written in Haskell, verifying certain properties of the compiler and catching regressions. If they fail, it looks like the python driver is informed, and then would report the error to the user.
phadej added:
FWIW GHC's built system is being rewritten to use shake: the Haskell library.
eacameron said:
I don't know. But GHC doesn't have the luxury of using Haskell the same way you and I do. It has to bootstrap using a previous version of itself and it wants to avoid dependencies. Python is a pretty light-weight requirement since most systems (except Windows) come with it built in.
The commit message introducing Python explains a lot of it:
Revamp the testsuite framework. The previous framework was an
experiment that got a little out of control - a whole new language
with an interpreter written in Haskell was rather heavyweight and left
us with a maintenance problem.
So the new test driver is written in Python. The downside is that you
need Python to run the testsuite, but we don't think that's too big a
problem since it only affects developers and Python installs pretty
easily onto everything these days.
Highlights:
790 lines of Python, vs. 5300 lines of Haskell + 720 lines of <strange made-up language>.
the framework supports running tests in various "ways", which should
catch more bugs. By default, each test is run in three ways:
normal, -O, and -O -fasm. Additionally, if profiling libraries
have been built, another way (-O -prof -auto-all) is added. I plan
to also add a 'GHCi' way.
Running tests multiple ways has already shown up some new bugs!
documentation is in the README file and is somewhat improved.
the framework is rather less GHC-specific, and could without much
difficulty be coaxed into using other compilers. Most of the
GHC-specificness is in a separate configuration file (config/ghc).
Things may need a while to settle down. Expect some unexpected
failures.

Statistical profiler for PyPy

I would like to use statprof.py for profiling code in PyPy. Unfortunately, it does not seem to work, the line numbers it points to are off. Does anyone know how to make it work or know of an alternative?
It's likely that "the line numbers are off" because PyPy, in JITted code, will inline many functions and will only deliver signals (here from the timer) at the end of the loops. Compare this with CPython, which delivers the signals between two random bytecodes -- occasionally at the end of the loops too, but generally anywhere. So what you get on PyPy is the same as what you'd get on CPython if you constrained the signal handlers to run only at the "end of loop" bytecode.
This is why this kind of profiling will seem to always miss a lot of functions, like most functions with no loop in them.
You can try to use the built-in cProfile module. It comes of course with a bigger performance hit than statistical profiling, but try it anyway --- it doesn't prevent JITting, for example, so the performance hit should still be reasonable.
More generally, I don't see an easy way to implement the equivalent of statistical profiling in PyPy. It's quite hard to give it sense in the presence of functions that are inlined into each other and then optimized globally... I'd be interested if you can find that a tool actually exists, for some other high-level language, doing statistical profiling, on a VM with a tracing JIT.
We could record enough information to track each small group of assembler instructions back to the real Python function it comes from, and then use hacks to inspect the current Instruction Pointer (IP) at the machine level. Not impossible, but serious work :-)

checking/verifying python code

Python is a relatively new language for me and I already see some of the trouble areas of maintaining a scripting language based project. I am just wondering how the larger community , with a scenario when one has to maintain a fairly large code base written by people who are not around anymore, deals with the following situations:
Return type of a function/method. Assuming past developers didn't document the code very well, this is turning out to be really annoying as I am basically reading code line by line to figure out what a method/function is suppose to return.
Code refactoring: I figured a lot of code need to be moved around, edited/deleted and etc. But lot of times simple errors, which would otherwise be compile time error in other compiled languages e.g. - wrong number of arguments, wrong type of arguments, method not present and etc, only show up when you run the code and the code reaches the problematic area. Therefore, whether a re-factored code will work at all or not can only be known once you run the code thoroughly. I am using PyLint with PyDev but still I find it very lacking in this respect.
You are right, that's an issue with dynamically typed interpreted languages.
There are to important things that can help:
Good documentation
Extensive unit-testing.
They apply to other languages as well of course, but here they are especially important.
As far as I know If code is not documented at all and the author isn't around anymore it's up to you to find out what the ode actually does.
That's why people should always stick to certain guidelindes that can be enforced by stylecheckers like pep8. https://pypi.python.org/pypi/pep8
Comments and docstrings should be included in every method to avoid such situation you're describing. http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring
Also unittests are very helpfull for refactoring since you can check if you broke something with the click of a button. http://docs.python.org/2/library/unittest.html
hope this helps
Others have already mentioned documentation and unit-testing as being the main tools here. I want to add a third: the Python shell. One of the huge advantages of a non-compiled language like Python is that you can easily fire up the shell, import your module, and run the code there to see what it does and what it returns.
Linked to this is the Python debugger: just put import pdb;pdb.set_trace() at any point in your code, and when you run it you will be dropped into the interactive debugger where you can inspect the current values of the variables. In fact, the pdb shell is an actual Python shell as well, so you can even change things there.

Is there a statistical profiler for python? If not, how could I go about writing one?

I would need to run a python script for some random amount of time, pause it, get a stack traceback, and unpause it. I've googled around for a way to do this, but I see no obvious solution.
There's the statprof module
pip install statprof (or easy_install statprof), then to use:
import statprof
statprof.start()
try:
my_questionable_function()
finally:
statprof.stop()
statprof.display()
There's a bit of background on the module from this blog post:
Why would this matter, though? Python already has two built-in profilers: lsprof and the long-deprecated hotshot. The trouble with lsprof is that it only tracks function calls. If you have a few hot loops within a function, lsprof is nearly worthless for figuring out which ones are actually important.
A few days ago, I found myself in exactly the situation in which lsprof fails: it was telling me that I had a hot function, but the function was unfamiliar to me, and long enough that it wasn’t immediately obvious where the problem was.
After a bit of begging on Twitter and Google+, someone pointed me at statprof. But there was a problem: although it was doing statistical sampling (yay!), it was only tracking the first line of a function when sampling (wtf!?). So I fixed that, spiffed up the documentation, and now it’s both usable and not misleading. Here’s an example of its output, locating the offending line in that hot function more accurately:
% cumulative self
time seconds seconds name
68.75 0.14 0.14 scmutil.py:546:revrange
6.25 0.01 0.01 cmdutil.py:1006:walkchangerevs
6.25 0.01 0.01 revlog.py:241:__init__
[...blah blah blah...]
0.00 0.01 0.00 util.py:237:__get__
---
Sample count: 16
Total time: 0.200000 seconds
I have uploaded statprof to the Python package index, so it’s almost trivial to install: "easy_install statprof" and you’re up and running.
Since the code is up on github, please feel welcome to contribute bug reports and improvements. Enjoy!
I can think of a couple of few ways to do this:
Rather than trying to get a stack trace while the program is running, just fire an interrupt at it, and parse the output. You could do this with a shell script or with another python script that invokes your app as a subprocess. The basic idea is explained and rather thoroughly defended in this answer to a C++-specific question.
Actually, rather than having to parse the output, you could register a postmortem routine (using sys.excepthook) that logs the stack trace. Unfortunately, Python doesn't have any way to continue from the point at which an exception occurred, so you can't resume execution after logging.
In order to actually get a stack trace from a running program, you will may have to hack the implementation. So if you really want to do that, it may be worth your time to check out pypy, a Python implementation written mostly in Python. I've no idea how convenient it would be to do this in pypy. I'm guessing that it wouldn't be particularly convenient, since it would involve introducing a hook into basically every instruction, which would I think be prohibitively inefficient. Also, I don't think there will be much advantage over the first option, unless it takes a very long time to reach the state where you want to start doing stack traces.
There exists a set of macros for the gdb debugger intended to facilitate debugging Python itself. gdb can attach to an external process (in this case the instance of python which is executing your application) and do, well, pretty much anything with it. It seems that the macro pystack will get you a backtrace of the Python stack at the current point of execution. I think it would be pretty easy to automate this procedure, since you can (at worst) just feed text into gdb using expect or whatever.
Python already contains everything you need to do what you described, no need to hack the interpreter.
You just have to use the traceback module in conjunction with the sys._current_frames() function. All you need is a way to dump the tracebacks you need at the frequency you want, for example using UNIX signals, or another thread.
To jump-start your code, you can do exactly what is done in this commit:
Copy the threads.py module from that commit, or at least the stack trace dumping function (ZPL license, very liberal):
Hook it up to a signal handler, say, SIGUSR1
Then you just need to run your code and "kill" it with SIGUSR1 as frequently as you need.
For the case where a single function of a single thread is "sampled" from time to time with the same technique, using another thread for timing, I suggest dissecting the code of Products.LongRequestLogger and its tests (developed by yours truly, while under the employ of Nexedi):
Whether or not this is proper "statistical" profiling, the answer by Mike Dunlavey referenced by intuited makes a compelling argument that this is a very powerful "performance debugging" technique, and I have personal experience that it really helps zoom in quickly on the real causes of performance issues.
To implement an external statistical profiler for Python, you're going to need some general debugging tools that let you interrogate another process, as well as some Python specific tools to get a hold of the interpreter state.
That's not an easy problem in general, but you may want to try starting with GDB 7 and the associated CPython analysis tools.
Seven years after the question was asked, there are now several good statistical profilers available for Python. In addition to vmprof, already mentioned by Dmitry Trofimov in this answer, there are also vprof and pyflame. All of them support flame graphs one way or another, giving you a nice overview of where the time was spent.
Austin is a frame stack sampler for CPython that can be used to make statistical profilers for Python that require no instrumentation and introduce minimal overhead. The simplest thing to do is to pipe the output of Austin with FlameGraph. However, you can just grab Austin's output with a custom application to make your very own profiler that is targeted at precisely your needs.
This is a screenshot of Austin TUI, a terminal application that provides a top-like view of everything that is happening inside a running Python application.
This is Web Austin, a web application that shows you a live flame graph of the collected samples. You can configure the address where to serve the application which then allows you to do remote profiling.
There is a cross-platform sampling(statistical) Python profiler written in C called vmprof-python.
Developed by the members of PyPy team, it supports PyPy as well as CPython.
It works on Linux, Mac OSX, and Windows. It is written in C, thus has a very small overhead.
It profiles Python code as well as native calls made from Python code.
Also, it has a very useful option to collect statistics about execution lines inside functions in addition to function names.
It can also profile memory usage (by tracing the heap size).
It can be called from the Python code via API or from the console.
There is a Web UI to view the profile dumps: vmprof.com, which is also open sourced.
Also, some Python IDEs (for example PyCharm) have integration with it, allowing to run the profiler and see the results in the editor.
For Python there is py-spy to dump the stacktraces. The dumps can get analyzed by speedscope
Source: Guidelines

What are good ways to make my Python code run first time? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm getting quite a few errors in my code. Consequently, I would like to be able to minimize them at the outset or see as many errors as possible before code execution. Is this possible and if so, how can I do this?
If you're having problems with syntax, you could try an editor with syntax highlighting. Until you get the feel for a language, simple errors won't just pop out at you.
The simplest form of debugging is just to insert some print statements. A more advanced (and extensible) way to do this would be to use the logging module from the std lib.
The interactive interpreter is a wonderful tool for working with python code, and IPython is a great improvement over the built-in REPL (Read Eval Print Loop).
If you actually want to step through your code, the python debugger is called pdb, which can be called from the command line, or embedded in your code.
If you're used to a fully integrated IDE, I would recommend using Eclipse with pydev, and PyCharm has a great commercial offering, with autocomplete, quick access to docs, and numerous shortcuts, among many other interesting features.
Here is some techniques to facilitate debugging in Python:
use interactive shell e.g., ipython. Python is a dynamic language you can explore your code as you type. The shell is running in the second window in my editor at all times.
copy-paste from the shell into docstrings a code that illustrates a dominant usage and corner cases of the function (class, module). doctest.testmod() placed in a if __name__=="__main__" section allows to test all docstrings in the module. doctest can be easily integrated with unittest.
use assert for stuff that can never happen.
print() can solve many debugging problems; logging module is suitable for long-living python processes.
write tests (not necessarily before your code), run them often (automatically or with one keystroke at most); nose provides extended test discovery and running features for unittest.
run pylint occasionally.
At this point there is a little use for a formal python debugger.
Winpdb is an external multi-platform GPL'ed GUI python debugger if you need one.
All the really cool stuff is easily demonstrated in the interactive interpreter. I think this might be the "gold standard" for good design:
Can you exercise your class interactively?
If you can do stuff interactively, then you can write unittests and doctests with confidence that it's testable, simple, reliable.
And, more important, you can explore it interactively. There's nothing better than the instant gratification that comes from typing code and seeing exactly what happens.
The compiled language habits (write a bunch of stuff, debug a bunch of stuff, test a bunch of stuff) can be left behind. Instead, you can write a little bit of stuff, explore it, write a formal test and then attach your little bit of stuff to your growing final project.
You still do overall design. But you don't squander time writing code that may or may not work. In Python you write code that works. If you're not sure, you play with it interactively until you're sure. Then you write code that works.
I am new to python, and have been trying several different debuggers. Here are the options I've come across so far:
Eclipse with Pydev - If you're already using eclipse, this is probably the way to go. The debugger works well, and is pretty featureful.
Komodo IDE - A light-weight python IDE. Basically a text editor + a debugger. It was really easy to figure out and be productive with immediately.
WinPDB - Trying this one next. Looks very featureful, and I get to use whichever editor I choose.
PDB - Haven't tried yet since I've read about how WinPDB is a better alternative.
Ipython with %run command - I've used IPython, but not as a debugger like this. I need to try this out. (Thanks for the tip, EOL)
Eric IDE - Also on the list to try.
Old-school print, assert statements - Simple, useful, but not a full solution.
Memory debugging - To debug memory problems, I've come across a few tools:
objgraph - Will generate png's of reference graphs. Neat. There's other functionality as well, like: import objgraph;print(objgraph.show_most_common_types(limit=10)) will print the top 10 most common types in memory.
gc module - Interact directly with the garbage collector.
heapy - Heap analyzer. For example: from guppy import hpy; hp = hpy(); print(hp.heap()) will print the most common types, their memory usage, etc.
This is a very incomplete list, but hopefully it's a good start.
Python provides a debugger which allows you to step through your code, inspect variables and manipulate them. Refer to http://pythonconquerstheuniverse.wordpress.com/category/python-debugger/ which can take you over the steps...
Also check the python standard library reference for pdb
http://www.python.org/doc/2.5.2/lib/module-pdb.html
Test early and test often.
This doesn't necessarily mean to jump into the test driven design pool head first (though that's not such a bad idea). It just means, test your objects and methods as soon as you have something that works. Don't wait until you have a huge pile of code before doing testing.
Invest some time in learning a testing framework. If it's trivial for you to type in a test case you'll more likely do it. If you don't have any sort of framework testing can be a pain so you'll avoid it. So, establish some good habits early on and you'll have fewer problems down the road.
More often than not, I just use a bunch of print statements.
page = grabpage(url)
print "Page content:", page
print "page type():", type(page)
It's sometimes useful to do something like:
debug = True
if debug: print "page content", page
..with this you can quickly disable all your debugging print statements by changing the debug variable to False.
While print-debugging will get you very far in most cases, sometimes it's difficult to debug things like loops, or a series of if/else/try/except/etc. For this a debugger that allows stepping though your code, and setting break-points is useful.
pdb is included with Python. Here is a good simple tutorial on it. You can even do things like changing variables during run-time (which the tutorial covers). A longer tutorial can be found here
There is a very nice GUI equivalent pdb - Winpdb
Basically you run winpdb myscript --arg 4 -b 4 then it loads the command in a terminal, shows you your code on the left, with the current, a list of local/global variables (and their values) and the current call-stack.
Then you can step though the code by clicking the Step (or F6). F5 runs the code. If you click next to the line numbers, it sets a break point, where the code will automatically step (when you press run).
I find it far easier to use, and it has lots of addition enhancements (like remote debugging, so you can run the backend portion (rpdb2) in the to-be-debugged application, and connect Winpdb to it (encrypted). It also has support for threading and other useful things not in PDB. You have access to a pdb-like console too.
I set up Python to automatically start the debugger when there's an uncaught exception, using this trick. That way, you can easily examine the state of the program without too much logging code. (Plus, to send me a Growl notification.)
Oh, and this way you can just create a break point in the code by adding
if answer == 42:
1/0
Using assert statement liberally.
Identifing errors before execution is the domain of static checking/analysis. I've had good luck using PyChecker for basic static checking of Python code.
The pycheesecake site has a very good summary of testing tools for Python.
The PyDev plugin for eclipse is my tool of choice. It recognizes simple syntax mistakes and indentation errors and underlines the error with a red line. It has a powerful debugger and even has a plugin called PyLint which warns you about dangerous code.
Edit:
It also has a user friendly stack trace on runtime errors, partial auto complete and some other nifty features.
Edit again:
I didn't notice that pydev was mentioned in the top post. I hope I brought something else to the table.
python -m pdb yourcode.py should do it.
Alternatively you can "import pdb" in your code and use pdb.set_trace() to set break points.
Refer the manual for more info: http://www.python.org/doc/2.5.2/lib/module-pdb.html
There is very nice GUI debugger for Python called Winpdb. Try it out.Built on wxWidgets library and multiplatform.
For a most integrated experience you can use full blown IDE like PyCharm:
http://blog.jetbrains.com/pycharm/files/2011/05/template-debug2.png
Eric4 IDE also has a great built-in debugger.
The IPython Python shell has a %pdb command that automatically invokes the debugger in case of problem. You can then inspect variables, step through the code, etc.
You can run your programs from IPython with the %run command.
More generally, as as been noted in some other answers, a good Python shell is your friend. And IPython is your best friend. :)

Categories