News for hackers. Stuff that matters.
Re:Why Python Is Slow: Looking Under the Hood by madengr on Tuesday November 18, 2014 @05:49PM (#8626907)
Please forgive my ignorance, but why can't Python just be compiled into assembly like C? The compiler should be able sift through the code and see that "x=1" is an integer, or converts to a float when "x=x+1.0".

If I'm doing something like counting from 1 to 10 and summing the count, why can't this be compiled to run the same speed as C?

Obviously since it's interpreted, but when I'm done with development, why can't I just run it through a compiler to get fast assembly code?

Way back when, you could get a BASIC compiler to turn your interpreted BASIC code into assembly.

What fundamental am I missing?

Re:Why Python Is Slow: Looking Under the Hood by jimbokun on Tuesday November 18, 2014 @06:25PM (#8627074)
What you describe is pretty much what functional languages with strong static typing, like Haskell, Scala, and Ocaml do. Works very well for examples like you gave: "x = 1", "x = x + 1.0". For expressions similar to these, inferring the types (int, float) works very well.

But things get much more complex very fast, and then the compiler requires the programmer to tell it what types things are.

Then there is the approach taken by JavaScript engines like V8. Run the code for a while, see what the types of variables are, then compile a customized, much more efficient version of the code to speed things up. Still need a fallback, though, in case a totally different kind of value gets stuck in a variable than the type at the time the optimized code was generated. Nothing in JavaScript (or Python) prevents a programmer from assigning any kind of value into a variable, though, so the engine must be prepared for the types of variables to change in unexpected ways.

(The reason the state of the art for these techniques is in the JavaScript engines is because the organizations behind the major browsers pour so many resources into making them fast.)

Now, if you can figure out a way to always predict the types of every variable in a JavaScript or Python program without actually running it, pretty much any CS program would be willing to give you a tenured position on their faculty on the spot. :)

Re:Why Python Is Slow: Looking Under the Hood by barsonme on Tuesday November 18, 2014 @07:11PM (#8627294)
If Python had the same amount of time and energy put into it that JavaScript does from Google and Mozilla it'd be willing to bet it'd be a lot faster.
Re:Why Python Is Slow: Looking Under the Hood by seunosewa on Wednesday November 19, 2014 @12:47AM (#8628462)
Like PyPy?
Re:Why Python Is Slow: Looking Under the Hood by vidarh on Tuesday November 18, 2014 @06:52PM (#8627203)
Python is similar in terms of dynamic features to Ruby. I'm actually working on an ahead of time "a static as possible" Ruby compiler.

You certainly can compile languages this dynamic, the problem is that the "simple" way of compiling it doesn't result in very fast code, because you essentially end up mimicking what the interpreters/vms do very closely, and a lot of what ends up being executed will be things like method lookups which are reasonably well optimized in the interpreters.

The problem boils down to the ability to "change the world" at almost any point.

E.g. in Ruby (don't know about Python), you can come back from an eval() call (or load or require) and find that the expression 1 + 1.0 results in the string "two", or will send you an insulting e-mail, because you can even override Fixnum#+.

Now, there's a lot that can be done to infer typing for these types of languages well enough that you can get away with slow-path fallbacks for the rare cases where users does something stupid (like override Fixnum#+) and run faster most of the time, but it's a lot of extra effort.

Re:Why Python Is Slow: Looking Under the Hood by dragonwriter on Tuesday November 18, 2014 @07:08PM (#8627280)
> The compiler should be able sift through the code and see that "x=1" is an integer, or converts to a float when "x=x+1.0".

The short version is "no, it shouldn't".

The longer version is that, viewing Python's runtime class memberships as "types", the type system it would represent is not one for which inference without explicit declarations is generally decidable, so an AOT compiler for unmodified, unrestricted Python that is expected to infer types at runtime simply would not be possible.

You could AOT compile it into C code with a lot of runtime metadata and indirections -- but that would probably have worse performance than the existing interpreter.

> Way back when, you could get a BASIC compiler to turn your interpreted BASIC code into assembly.

Well, yeah, BASIC is actually structurally quite close to assembly. Its not a dynamically-typed multiparadigm language like Python.

Re:Why Python Is Slow: Looking Under the Hood by JoeAltmaier on Tuesday November 18, 2014 @07:11PM (#8627297)
Its hard to be worse than an interpreter. 100X slower than compiled code is typical. Whatever 'metadata and indirection' your C target has, it seems likely to be 10X better than interpreted, easily.
Re:Why Python Is Slow: Looking Under the Hood by dagw on Wednesday November 19, 2014 @03:43AM (#8628912)
Cython is a very mature python-to-C translator and it offers 0-40% speed improvements in my experience on straight Python. To get any significant speedups you have to add type declarations, replace python function with equivalent C functions from the standard library, turn off bounds checking and bunch of similar things. But if you do that then it does produce some pretty fast code.
Re:Why Python Is Slow: Looking Under the Hood by dragonwriter on Tuesday November 18, 2014 @07:30PM (#8627400)
> Its hard to be worse than an interpreter.

Its actually quite easy to be worse than an interpreter that is actually a combination of a bytecode compiler and a VM built around the execution model of the language it is for, which is what the main Python interpreter is.

Re:Why Python Is Slow: Looking Under the Hood by JoeAltmaier on Wednesday November 19, 2014 @10:42AM (#8630584)
Interpreters have to be implemented somehow; that's a way. Its not fast. Its orders of magnitude slower than native code. Even bad native code.
Re:Why Python Is Slow: Looking Under the Hood by ovis on Tuesday November 18, 2014 @06:15PM (#8627040)
I believe that's essentially what Cython allows you to do, by way of C. Since the Cython compiler isn't especially advanced, it requires some hints to get good performance, which is why Cython code is usually typed, structured more like C, etc. But still, it executes on your basic idea.
Re:Why Python Is Slow: Looking Under the Hood by kyllo on Tuesday November 18, 2014 @06:13PM (#8627028)
Runtime metaprogramming. In Python you can create new classes and add methods to existing classes at runtime. If you AOT-compile everything to assembly, you have to take away those runtime features, and then it's not Python anymore.
Re:Why Python Is Slow: Looking Under the Hood by vidarh on Tuesday November 18, 2014 @08:17PM (#8627600)
No, you don't. You "just" need slower fallbacks that does metadata lookup for things that are not statically decidable.

Consider how many people end up implement their own introspectable C object models.

Re:Why Python Is Slow: Looking Under the Hood by chrisseaton on Tuesday November 18, 2014 @09:16PM (#8627841)
I think the very real risk here is that you think you're adding those slower fallback features just for edge cases, but in reality they get used in the majority of cases.

I believe that some code paths critical for performance in Rails use metaprogramming, for example.

I did an experiment in this paper http://dl.acm.org/citation.cfm?id=2647517&dl=ACM&coll=DL&CFI... where I showed that just be rearranging some code you can confuse the Rubinius object allocator into using a slow path for instance variables. That gives you both slow performance, and worse than that, unpredictable performance - the programmer doesn't understand what they've done wrong to trigger that fallback performance.

Re:Why Python Is Slow: Looking Under the Hood by plikan13 on Tuesday November 18, 2014 @06:28PM (#8627084)
Why can't a C++ compiler optimize away virtual function tables? If a C++ compiler could deduce the exact derived type of all objects at compile time, it could call the correct virtual function statically instead of going through the extra indirection at runtime.
Re:Why Python Is Slow: Looking Under the Hood by zanny on Tuesday November 18, 2014 @07:36PM (#8627429)
If you declare a C++ virtual function final the compiler can avoid the virtual call table for any invocations of that function in the future on that object or any of its derivatives. Of course, you then cannot override it in child classes anymore.

If you declare a virtual function inline, if it is invoked from a well defined object (ie, not through a reference or pointer) you also get a similar effect while still being able to override, except the code is not a static call but is just inlined with that one implementation of the function.

Re:Why Python Is Slow: Looking Under the Hood by pjmlp on Wednesday November 19, 2014 @01:56AM (#8628634)
It can, but not across dynamic libraries.

You just need to use profile guided optimisation.

Re:Why Python Is Slow: Looking Under the Hood by joe_the_user on Tuesday November 18, 2014 @05:59PM (#8626963)
The problem is that an average interpret/compiler is going to be "dumb" in that it assumes that when it starts parsing a python file that all of the features are going to be used.

It provides facilities for all of python abilities regardless of what the program is going to do.

Now, there are subsets of python people have developed that can be compiled and all sorts of other stuff.

Beyond that, I'd just say "all this stuff sounds easy but gets much harder when you actually have to program it".

"Why can't it just know!" is the programmer's lament.

Re:Why Python Is Slow: Looking Under the Hood by cityhall on Tuesday November 18, 2014 @10:26PM (#8628059)
Cython, numba, and other projects do this for a subset of the language, but you lose the metaprogramming that makes things like SQLAlchemy possible. You also have to treat most user objects as hashmaps and constantly look up their fields since members can be added or redefined at any time.
Re:Why Python Is Slow: Looking Under the Hood by keypusher on Wednesday November 19, 2014 @12:28AM (#8628434)
Write a function. It accepts two variables. Add them both together and return the result. What type is returned?

Read input from a file or stdin. Eval that input. What type does it return?

Etc.

Re:Why Python Is Slow: Looking Under the Hood by timClicks on Tuesday November 18, 2014 @05:59PM (#8626962)
I don't know the full story either, but I expect it's because lots of things change during runtime. It's too hard to lock things down.