Mixpanel: Scaling to the Internet - Writing C extensions for Python
code.mixpanel.com
code.mixpanel.com
There are many options to speed up your Python code by ~50 times effortlessly. See my blog posts:
http://kayhayen24x7.homelinux.org/blog/2010/09/nuitka-releas...
http://docs.python.org/library/profile.html http://wiki.python.org/moin/PythonSpeed/PerformanceTips
As an aside some simple coding changes will allow Psyco to do much of the by hand optimisations that Cython gives you. Not all and it is easy for another coder to come along and ruin everything. All it takes is some understanding of how Psyco performs its magic.
Let me introduce you to Cython.
As the author shows, writing a python c extension is fundamentally easy which is why Python has such a huge ecosystem of them to begin with.
If dependency for distribution is an issue, you can just include the generated C code (as we do in numpy and scipy, as a matter of fact). Also, cython can generate both python 2 and 3 compatible code.
In fact, if you set up the gateway interface to your C code cleanly, you can have the same C code callable directly from (e.g.) Matlab via the "mex" mechanism.
http://www.artima.com/weblogs/viewpost.jsp?thread=95863
"But even if I find the cause of the leak, I may not be able to plug it. M2Crypto is written using SWIG, which contains lots of obfuscated code and doesn't exactly give me a warm fuzzy feeling that it's always doing the reference counting correctly."
I prefer a clean handwritten C extension any day. There is a lot of repetitive work involved, but most of that is really just copy&paste, so it tends to go quickly.
This method is so productive it always surprises me how quickly things get done!
That's why something like numpy manages to be so fast if used well: it internally uses efficient (C-like) representation, but as soon as you need to interact with every item in your array, then it is not only much slower, but even slower than using standard python containers because of this cost.
I know when I write an XS extension in Perl, though, that getting the C struct associated with my Perl object requires one C function call -- no overhead at all. Passing an object to Perl involves allocating memory and adjusting the pointers. All very fast. If this sort of thing is your bottleneck, it's time to step back and rethink what you are trying to achieve.
For example, I wrote a few years ago a small audio app to track frequencies lines in audio. Each track was a list of positions (integers), generally a few tens items max, and I needed to handle millions of such lists. Now, just optimizing the track object to be in C is not that efficient because I needed to access the content of each list in the high level logic.
Basically, If your logic needs to be able to handle those millions small objects, you end up writing almost everything in the compiled language. Abstracting this becomes very difficult.
http://hackage.haskell.org/packages/archive/vector/0.7/doc/h...