- A very-low-overhead JIT using DynASM
- Quickening
- Aggressive attribute caching
- General CPython optimizations
- Build process improvements
3,205 karma · joined July 24, 2009
- A very-low-overhead JIT using DynASM
- Quickening
- Aggressive attribute caching
- General CPython optimizations
- Build process improvements
- People actually use the "hard to implement" parts of the C API
- Moving things from macros to function calls can often be quite detrimental to performance
- C extensions have been co-optimized with the C API, so changing the C API will make things less optimized
- These "check if runtime debugging is enabled" checks are not free
My guess is that this will end up in a tough middle ground where extension writers will be faced with a tradeoff along the lines of making their extension 10% slower for 99% of their users in order to make things 2x faster for 1% of their users.
So I would not call this "scientific computing". Personally I consider competitive programming to be it's own use case.
And as much as we want to improve scientific computing in Python, it's very hard since the work is done in C. Our current hope is to help mixed workloads, such as doing a decent amount of data-preprocessing in Python before handing off to C code.
While we could certainly go in this direction, we're not planning to, because in our experience optimizations for different workloads are largely distinct, and this use case is already handled well by PyPy.
- In the blog post I linked to an issue of someone trying to upstream a quickening implementation and meeting resistance due to the added complexity
- CPython prefers portability over performance, and we added a number of big build dependencies that may not work on all the platforms that CPython supports, though from our perspective it works on all the important ones
- CPython has included a number of performance-degrading features over the years and we plan to start cutting out some that are only used for debugging but still hurt release mode. I don't know for sure but I would expect resistance to backing out those changes.
There are more, but the general idea is that the two projects will make different tradeoffs. Maybe there is a world where the code all lives in the same repository but is gated between different behaviors, but the CPython maintainers have already rejected a proposal like that.
- There are companies which would be willing to pay large amounts of money (more than he's asking for) for the speedups he's promising
- There are other similar efforts underway (such as ours) which have implemented some of his ideas and the gains are much smaller than he anticipates (for real code, microbenchmarks are another story)
For a project blog I used hosted wordpress, and I found that to be a pretty good middle ground. Honestly I can't think of a case where running your own wordpress server is a good use of your time.
Just look at the small example in this post: - converting things to strings invokes several layers of dynamic dispatches - Python has an extremely expressive calling convention that can cause a lot of overhead
Another example that I like to give is that in Python you can inspect the stack variables of exited frames! The Python-on-mature-VM projects have also not resulted in great performance.
I hear your argument a lot, and I disagree and I also believe it misguides optimization efforts ("let's just apply JS techniques to Python") including our early ones with Pyston. It's part of what I'm trying to get at with this blog post, but maybe I'll write another one specifically about Python vs other languages.
static PyObject *
unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *x = NULL;
static char *kwlist[] = {"object", "encoding", "errors", 0};
char *encoding = NULL;
char *errors = NULL;
PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:str",
kwlist, &x, &encoding, &errors))
}
Notice the call to PyArg_ParseTupleAndKeywords -- it takes an arguments tuple and a format string and executes a mini interpreter to parse the arguments from the tuple. It has to be ready to receive arguments as any combination of keywords and positional, but for a given callsite the matching will generally be static.We definitely agree directionally: you can create specific implementations of operations that are fast for their inputs. But look at how specific we have to get here. It's not just on the type of the callable: we have to know the exact callable we are calling (the str type). And its behavior is heavily dependent on its argument type. So we need a code path that is specifically for calling the str() function on ints. I would argue that this is prohibitively specialized for an interpreter, but one can imagine a JIT that is able to produce this kind of specialization, and that's exactly what this blog post is trying to motivate.
I didn't read all their math but I expect their final result to be off by a factor of 2-5x. Hard drives are a surprisingly low percentage of the cost of a storage system.