Live data from Hacker News

Performance of the Python 3.14 tail-call interpreter

blog.nelhage.com

91–100 of 180 posts

Re: Performance of the Python 3.14 tail-call interpreter

#91
post #15

Earlier quoted context omitted.

> The C expression `a += 1` can be trusted to increment a numeric value, [...] Have you heard of undefined behaviour?

Show me a C compiler that miscompiles the following code and I'll concede the point: uint32_t add_1(uint32_t a) { a += 1; return a; }

[deleted]

Re: Performance of the Python 3.14 tail-call interpreter

#92
post #77

Earlier quoted context omitted.

Why would you want it to increment 1 if we decrement 1 from the same variable? That would be a waste of cycles and a good compiler knows how to optimize it out, or what am I misunderstanding here? What do you expect "it" to do and what does it really do? See: https://news.ycombinator.com/item?id=43320495

That’s a contrived example but in a serious program there would often be code in between or some level of indirection (e.g. one of those values is a lookup, a macro express, or the result of another function). Nothing about that is cheating, it just says that even C programmers cannot expect to look at the compiled code and see a direct mapping from their source code. Your ability to reason about what’s actually exec…

In what languages can you do that that is not assembly though? The higher level the language is, the "worse" or difficult it gets, perhaps I am not following the thread right.

Re: Performance of the Python 3.14 tail-call interpreter

#93

Earlier quoted context omitted.

All of those look pretty straightforward to me -- again, what assembly would you expect to be emitted in those cases? For contrast, here's the assembly generated for Haskell for integer addition: https://godbolt.org/z/vdeMKMETT And here's assembly for C++: https://godbolt.org/z/dedcof9x5

> All of those look pretty straightforward to me -- again, what assembly would you expect to be emitted in those cases? It is very straightforward indeed, but it is still not mapping primitive operations to direct machine code, but it is forwarding to out-of-line code. Same as operator overloading in other languages. > And here's assembly for C++: https://godbolt.org/z/dedcof9x5 That's just a symptom of allowing the…

  > It is very straightforward indeed, but it is still not mapping primitive
  > operations to direct machine code, but it is forwarding to out-of-line code.
  > Same as operator overloading in other languages.
I am not claiming that C is a collection of assembler macros. There is no expectation that a C compiler emit machine code that has exact 1:1 correspondence with the input source code.

  > Same as operator overloading in other languages.
The lack of operator overloading, and other hidden complex control flow, is the reason that someone can read C code and have a pretty good idea of what it compiles to.

  > That's just a symptom of allowing the compiler to inline the add code,
  > otherwise the generated code is as straightforward:
No, that's just moving the instructions around. You've still got dynamic allocation and stack-unwinding being generated for a line that doesn't have any sign of entering a complex control flow graph.

Re: Performance of the Python 3.14 tail-call interpreter

#94

Earlier quoted context omitted.

Why would you want it to increment 1 if we decrement 1 from the same variable? That would be a waste of cycles and a good compiler knows how to optimize it out, or what am I misunderstanding here? What do you expect "it" to do and what does it really do? See: https://news.ycombinator.com/item?id=43320495

I'm pretty sure that's replying directly to the comment about how c is close to assembly and that if you add that line of code somewhere you know there's a variable getting incremented. Doesn't really matter whether or not it's useful, the point is that the behavior isn't exactly what you wrote

https://godbolt.org/z/r39jK1ddv

It increments, then decrements with -O0 though.

I do not see the issue still, as the behavior is expected with -O0; increments then decrements.

Re: Performance of the Python 3.14 tail-call interpreter

#95
post #87

Earlier quoted context omitted.

Why would you want it to increment 1 if we decrement 1 from the same variable? That would be a waste of cycles and a good compiler knows how to optimize it out, or what am I misunderstanding here? What do you expect "it" to do and what does it really do? See: https://news.ycombinator.com/item?id=43320495

I'm not an embedded expert but a friend of mine has complained about compiler optimizations breaking things in his programs. I could see incrementing by one being used to set some bits in a memory location for a cycle that may mean something to some peripheral and then decrementing by one to set some other bits that may mean something else. In that case, the compiler removing those two lines would cause a very hard t…

I understand compiler optimizations having unintended consequences, e.g. https://godbolt.org/z/r39jK1ddv but there are a lot of options he may use to enable or disable optimizations (assuming GCC here): https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

This is even more difficult to do with higher-level languages.

Re: Performance of the Python 3.14 tail-call interpreter

#96

Earlier quoted context omitted.

When the code has hit the IR in clang or gcc, there is no 'a' (we know that with certainty, since SSA form doesn't mutate but assigns to fresh variables). We don't know if there will be an increment of 1, the additions could be coalesced (or elided if the result can be inferred another way). The number can even decrease, say if things have been handled in chunks of 16, and needs to be adjusted down in the last chunk.…

From a high-level academic view, yes, the compiler is allowed to perform any legal transformation. But in practice C compilers are pretty conservative about what they emit, especially when code is compiled without -march= . You don't have to take my word for it. Go find a moderately complex open-source library written in C, compile it, then open up the result in Hexrays/Ghidra/radare2/whatever. Compare the compiled f…

They are as aggressive as they can be.

Here's an example of a C compiler completely eliminating a loop because it has figure out how to transform the loop into a constant calculation.

https://godbolt.org/z/cfndqMj4j

The place where C compilers are conservative is when dealing with arrays and pointers. That's because it's impossible for C to know if a pointer is to an element of an array or something completely different. Pointer math further complicates what a pointer could actually reference.

Re: Performance of the Python 3.14 tail-call interpreter

#97

Earlier quoted context omitted.

Show me a C compiler that miscompiles the following code and I'll concede the point: uint32_t add_1(uint32_t a) { a += 1; return a; }

If my misocompile, you mean that it fails the test that a "C expression `a += 1` can be trusted to increment a numeric value", then it is trivial: https://godbolt.org/z/G5dP9dM5q

Here's another one, just for fun https://godbolt.org/z/TM1Ke4d5E

Re: Performance of the Python 3.14 tail-call interpreter

#98
post #60
post #28

Earlier quoted context omitted.

C might be low level from the perspective of other systems languages, but that is like calling Apollo 11 simple from the perspective of modern spacecraft. C as written is not all that close to what actually gets executed. For a small example, there are many compilers who would absolutely skip incrementing 'a' in the following code: uint32_t add_and_subtract_1(uint32_t a) { a += 1; a -= 1; return a; } Even though that…

If you want the compiler to treat your code as literal portable assembly turn off optimizations.

Exactly, pretty much what I said, or enable / disable the optimizations you want.

Re: Performance of the Python 3.14 tail-call interpreter

#99

Great article! One detail caught my attention. In one of the referenced articles, https://simonwillison.net/2025/Feb/13/python-3140a5/ , the author wrote: "So 3.14.0a5 scored 1.12 times faster than 3.13 on the benchmark (on my extremely overloaded M2 MacBook Pro)." I'm quite confused by this. Did the author run the benchmark while the computer was overloaded with other processes? Wouldn't that make the results comple…

Simon Willison is a great guy, but he's not a Python core developer and his ad hoc benchmark is not what the CPython core team members are using. For the latter, see https://github.com/faster-cpython/benchmarking-public
Post reply on HN