Live data from Hacker News

How many lines of C it takes to execute a + b in Python

codeconfessions.substack.com

181–190 of 224 posts

Re: How many lines of C it takes to execute a + b in Python

#181
post #136

Earlier quoted context omitted.

Can someone explain what exactly it is about Python's design that makes it slow? What changes would have to be made to speed it up? Obviously changing its core design now would break things, but my question is, can we can imagine an alternate universe Python that's as close as possible to our Python, except really fast? What would be different?

I am going to answer this question in a roundabout way: first showing examples of different code gen in Rust, because it is more straightforward, but then I will reach for an example with Ruby, because I know it better than Python, but I believe it is similar enough that you will get the gist. If I write a function like this in Rust: pub fn add(x: i32, y: i32) -> i32 { x + y } this will compile to this assembly (on x…

You should have added Ruby JITs into the explanation, with the related generated Assembly code. :)

Re: How many lines of C it takes to execute a + b in Python

#182
post #178

Earlier quoted context omitted.

Unfortunately Python's innard is much more complicated than most expectations. You have named JS and Lua, but those languages never have "magic" methods---JS instead has prototypes and more recently proxies, while Lua has metatables. Ordinary objects aren't magic in this sense, and conversely magical objects are generally deliberate choices in those languages. But Python's magic `__dunder__` methods are everywhere in…

Smalltalk, SELF and Common Lisp are full of dynamic magic, you can in a single function call change the representation of all instances of a given object during program execution, at any given time break into the debugger and change whatever you feel like and resume execution, dynamically load code from the network with side effects on the running program, and many other crazy things. Yet, not only are they in the ge…

Is there any direct comparison though? Because it can be alternatively argued that these dynamic languages needed new JIT techniques for performance, but they especially work well for more constrained languages like JS. I don't think Smalltalk was ever a good fit for number crunching, for example.

Re: How many lines of C it takes to execute a + b in Python

#183
post #178

Earlier quoted context omitted.

Smalltalk, SELF and Common Lisp are full of dynamic magic, you can in a single function call change the representation of all instances of a given object during program execution, at any given time break into the debugger and change whatever you feel like and resume execution, dynamically load code from the network with side effects on the running program, and many other crazy things. Yet, not only are they in the ge…

Is there any direct comparison though? Because it can be alternatively argued that these dynamic languages needed new JIT techniques for performance, but they especially work well for more constrained languages like JS. I don't think Smalltalk was ever a good fit for number crunching, for example.

Better than CPython, regardless of how you put it.

EDIT:

Also to note, those languages powered whole graphical single workstations, with microcoded CPUs + JIT.

"Efficient implementation of the smalltalk-80 system"

https://dl.acm.org/doi/10.1145/800017.800542

https://computerhistory.org/blog/introducing-the-smalltalk-z...

"Self-Confidence: How SELF Became a High-Performance Language"

https://www.cs.cornell.edu/courses/cs6120/2020fa/blog/self/

Re: How many lines of C it takes to execute a + b in Python

#184
post #122

Earlier quoted context omitted.

In the late 1990s and early 200xs, there were a lot of claims that there was no such thing as a "slow language", that all languages can be run as quickly as C if you just built a sufficiently smart compiler and/or runtime. I haven't heard anyone make this claim in a while. The inability to speed up Python beyond a certain point despite a lot of clever approaches taken was probably a good chunk of the reason, the rema…

I think this is really complicated. I do believe that it is important to separate language from implementation, and it is also true that different implementations can have different performance profiles. It is also true that the semantics of the language can effectively require specific implementation details that can affect performance either way. So there's always gonna be bounds to any particular languages' abilit…

It certainly is complicated.

And I'd love to peer in to some alternate universe that has an optimal Python interpreter (can't say "the" optimal because it's really a complicated frontier rather than a single point) that runs on our hardware and see what it looks like. Maybe even on multiple points on that frontier.

What really is the limit? I struggle to imagine what a C-speed Python interpreter could even look like, but is there some conceivable program that runs it at, say, half the speed? What even is the limit? What techniques would such a program use that would surprise us and be new and perhaps useful other places?

Or are actually pretty close to that frontier now?

To be honest, given the way optimizations tend to work, the answer probably is that we are relatively close today. They tend to have diminishing returns.

But I don't know. Is there some execution model nobody's thought of, or that has been thought of but simply hasn't had the effort invested to make it pay off, that would make huge gains? I can't prove there isn't. (In fact it's not far off junior-level computer science to prove that you can't prove it.)

Re: How many lines of C it takes to execute a + b in Python

#185
post #122

Earlier quoted context omitted.

In the late 1990s and early 200xs, there were a lot of claims that there was no such thing as a "slow language", that all languages can be run as quickly as C if you just built a sufficiently smart compiler and/or runtime. I haven't heard anyone make this claim in a while. The inability to speed up Python beyond a certain point despite a lot of clever approaches taken was probably a good chunk of the reason, the rema…

> In the late 1990s and early 200xs, there were a lot of claims that there was no such thing as a "slow language", that all languages can be run as quickly as C if you just built a sufficiently smart compiler and/or runtime. I think "slow language" never meant that way. It was more like a counterpoint to the claim that there are inherent classes of languages in terms of performance, so that some language is (say) 100…

"If you have used Python long enough you may know that Python originally had two types of classes"

Yes, because that's also the era where this claim was flying around.

I'd say that each individual person may have their own read on what the claim meant, but certainly the way it was deployed at anyone who vaguely complained that Python was kind of slow shows that plenty of people in practice read it as I've described... that if we just wait long enough and put enough work into it, there would be no performance difference between Python and C. In 2023 we can look back with the perspective that this seems to be obviously false, so they couldn't possible have meant that, but they didn't have that perspective, and so yes they can have meant that. "Sufficiently smart compiler" was just starting to be a derogatory term. I also remember and lightly participated in the c2.com discussions on that, which may also contribute to my point that, yes, there definitely were people who truly believed "sufficiently smart compilers" could exist and were just a matter of time.

As for proportions, it's impossible to tell. Internet discussions (yea verily including this very one) in general are difficult to ascertain that from because almost by definition only outliers are participating in the discussion at all. Obviously by bulk of programmers, most programmers had simply never considered the question at all.

Re: How many lines of C it takes to execute a + b in Python

#186

Earlier quoted context omitted.

Arguably those redesigns might have happened if the Python 2->3 transition hadn't received a decade of extremely vocal pushback

What’s funny is the breaking change that caused us the most headaches with 2->3 was the changes to fucking print. I’m still finding broken print as a statement instead a function issues in codebases, somehow.

It’s the easiest one to fix, though. 2to3 does it easily. If it were the only change, we would not be having this conversation. It might have even not deserved a major version bump (given that even minor releases of Python don't conserve backwards compatibility).

Re: How many lines of C it takes to execute a + b in Python

#187
post #56
post #54

Earlier quoted context omitted.

Leaving aside the apparent confusion between C and C++, do you really imply overloading could make adding two fixed size numbers in Python take unbounded time?

I'm saying a + b in Python can do whatever you override the __add__/__radd__ to. Not sure why you invoke C/C++ here. If you only limit yourself to numbers (the title doesn't specify that) it should be bounded, but the article goes into some depth here, so I'll leave it at that.

But this has nothing to do with the halting problem. You can run the code, you don't need to do this theoretically.

Re: How many lines of C it takes to execute a + b in Python

#188
post #184

Earlier quoted context omitted.

I think this is really complicated. I do believe that it is important to separate language from implementation, and it is also true that different implementations can have different performance profiles. It is also true that the semantics of the language can effectively require specific implementation details that can affect performance either way. So there's always gonna be bounds to any particular languages' abilit…

It certainly is complicated. And I'd love to peer in to some alternate universe that has an optimal Python interpreter (can't say "the" optimal because it's really a complicated frontier rather than a single point) that runs on our hardware and see what it looks like. Maybe even on multiple points on that frontier. What really is the limit? I struggle to imagine what a C-speed Python interpreter could even look like,…

Yep, that'd be a lot of fun. I think back to the stuff that used to go on to optimize lua: http://lua-users.org/lists/lua-l/2011-02/msg00742.html

I also suspect that we are relatively close, and there are diminishing returns. I suspect that you would have to start the language design with this goal in mind, and then balance out performance concerns with certain features.

Re: How many lines of C it takes to execute a + b in Python

#189
post #181

Earlier quoted context omitted.

I am going to answer this question in a roundabout way: first showing examples of different code gen in Rust, because it is more straightforward, but then I will reach for an example with Ruby, because I know it better than Python, but I believe it is similar enough that you will get the gist. If I write a function like this in Rust: pub fn add(x: i32, y: i32) -> i32 { x + y } this will compile to this assembly (on x…

You should have added Ruby JITs into the explanation, with the related generated Assembly code. :)

Yeah that would be fun but I don't have a Ruby environment installed and the comment is already getting very long; if I ever turn this into a blog post someday maybe I will add that :)

Re: How many lines of C it takes to execute a + b in Python

#190
post #178

Earlier quoted context omitted.

Smalltalk, SELF and Common Lisp are full of dynamic magic, you can in a single function call change the representation of all instances of a given object during program execution, at any given time break into the debugger and change whatever you feel like and resume execution, dynamically load code from the network with side effects on the running program, and many other crazy things. Yet, not only are they in the ge…

Is there any direct comparison though? Because it can be alternatively argued that these dynamic languages needed new JIT techniques for performance, but they especially work well for more constrained languages like JS. I don't think Smalltalk was ever a good fit for number crunching, for example.

So if one was "Prototyping a Real-Time Embedded System in Smalltalk" one might 'improve frequently invoked methods by recoding, possibly as “primitive” functions in a lower level language such as C or assembler'.

https://dl.acm.org/doi/pdf/10.1145/74878.74904

Post reply on HN