Live data from Hacker News

Python 3.13 Gets a JIT

tonybaloney.github.io

411–420 of 553 posts

Re: Python 3.13 Gets a JIT

#411
post #41
post #36

Earlier quoted context omitted.

maybe, maybe not. time will tell. ahead-of-time compilation is even better known for improving performance and yet perl's compile-to-c backend turned out to fail to do that

Ahead-of-time compilation is a bad solution for dynamic languages, so that is an expected outcome for Perl. The base line should be how heavily dynamic languages like my favourite set, Smalltalk, Common Lisp, Dylan, SELF, NewtonScript, ended up gaining from JIT, versus the original interpreters, while being in the genesis of many relevant papers for JIT research.

JIT compilation is rare in Common Lisp. I wouldn't think that Dylan implementations used JIT compilation.

Apple's Dylan IDE and compiler was implemented in Macintosh Common Lisp (MCL). MCL then was not a part of the Dylan runtime.

I would think that Open Dylan (the Dylan implementation originally from Harlequin) can also generate LLVM bitcode, but I don't know if that one can be JIT executed. Possibly...

Re: Python 3.13 Gets a JIT

#412
post #294

Earlier quoted context omitted.

What is the programming analogy here? Two decades ago, you could (as e.g. Paul Graham did at the time) argue that dynamically typed languages can get your ideas to market faster so you become viable and figure out optimization later. It's been a long time since that argument held. Almost every dynamic programming language still under active development is adding some form of gradual typing because the maintainability…

I cut my teeth on C/C++, and I still develop the same stuff faster in Python, with which I have less overall experience by almost 18 years. Python is also much easier to learn than, say, Rust, or the current standard of C++ which is a veritable and intimidating behemoth. In many domains, it doesn't really matter if the resulting program runs in 0.01 seconds or 0.1 seconds, because the dominant time cost will be in us…

> Python is also much easier to learn than, say, Rust

I don't doubt it, but learning is only the first step to using a technology for a series of projects over years or even decades, and that step doesn't last that long.

People report being able to pick up Rust in a few weeks and being very productive. I was one of them, if you already got over the hill that was C++ then it sounds like you would be too. The point is that you and your team stay that productive as the project gets larger, because you can all enforce invariants for yourselves rather than have to carry their cognitive load and make up the extra slack with more testing that would be redundant with types.

Outside of maybe a 3 month internship, when is it worthwhile to penalize years of software maintenance to save a few weeks of once-off up-front learning? And it's not like you save it completely, writing correct Python still takes some learning too, e.g. beginners easily get confused about when mutable data structures are silently being shared and thus modified when they don't expect it. People who are already very comfortable with Python forget this part of their own learning curve, just like people very comfortable with Rust forget their first borrow check header scratcher.

I never made a performance argument in this thread so I'm not sure why 0.01 or 0.1 seconds matters here. Even the software that got you into a commercial market has to be maintained once you get there. Ask Meta how they feel about the PHP they're stuck with, for example.

Re: Python 3.13 Gets a JIT

#413
post #397

Earlier quoted context omitted.

I like python but I would never choose it for anything more than trivial on the backend. I want to know what types are being passed around from one middleware function to the next. Yes python has annotations but that’s not enough.

Just wait until you see what the enterprise Java developers passing around with type Object and encoded XML blobs. Type checking is really useful but it can be defeated in any language if you don’t have a healthy technical culture.

Is that why I see much object serialization/deserialization in Java?

They're trying to pass data between layers of middleware, but Java has very strict typing, and the middleware doesn't know what kind of object it will get, so it has to do tons of type introspection and reflection to do anything with the data?

Re: Python 3.13 Gets a JIT

#414
post #256

Earlier quoted context omitted.

Given how many Microsoft employees today steer the Python decision making process, I'm sure in not so distant future, we might see a new CLR-based Python implementation. Maybe Microsoft don't know yet how to sell this thing, or maybe they are just boiling the frog. Time will tell. But I'm pretty sure your question will be repeated as soon as people will get used to the idea of Python on JIT.

Doesn't this already exist in IronPython?

It's a lot about popularity / stigma.

Microsoft developed both JScript and Node.js. They could've continued with JScript, but obviously decided against it because JScript didn't earn the reputation they might have hoped for. Even if they invested efforts into rectifying the flaws of JScript, it would've been just too hard to undo the reputation damage.

Microsoft made multiple attempts to "befriend" Python. IronPython was one of the failures. They also tried to provide editing tools (eg. intellisense in MSVS), but kind of given up on that too (but succeeded to a large degree with VSCode).

The whole long-term Microsoft's strategy is to capture and put the developers on a leash. They won't rest until there's a popular language they don't control.

Re: Python 3.13 Gets a JIT

#415
post #168

Earlier quoted context omitted.

so then the remaining performance-critical case is where you have a big array of floats you're looping over. in firefox that works fine (one allocation per lowest-level array, not one allocation and unprefetchable pointer dereference per float), but maybe in chrome you'd want to use a typedarray?

As I understand it, V8 keeps track of an ElementsKind for each array (or, more precisely, for the elements of every object; arrays are not special in this sense). If an array only contains floats, then they will all be stored unboxed and inline. See here: https://source.chromium.org/chromium/chromium/src/+/main:v8/... I assume that integers are coerced to floats in this mode, and that there's a performance cliff if y…

thank you for the correction!

Re: Python 3.13 Gets a JIT

#416
post #411
post #41

Earlier quoted context omitted.

Ahead-of-time compilation is a bad solution for dynamic languages, so that is an expected outcome for Perl. The base line should be how heavily dynamic languages like my favourite set, Smalltalk, Common Lisp, Dylan, SELF, NewtonScript, ended up gaining from JIT, versus the original interpreters, while being in the genesis of many relevant papers for JIT research.

JIT compilation is rare in Common Lisp. I wouldn't think that Dylan implementations used JIT compilation. Apple's Dylan IDE and compiler was implemented in Macintosh Common Lisp (MCL). MCL then was not a part of the Dylan runtime. I would think that Open Dylan (the Dylan implementation originally from Harlequin) can also generate LLVM bitcode, but I don't know if that one can be JIT executed. Possibly...

are there any cl implementations that use jit? there are a lot of cl implementations so i assumed there must be one

Re: Python 3.13 Gets a JIT

#417

The article presents a copy and patch jit as something new, but I remember DOS's quickbasic doing the same thing. It generated very bad assembly code in memory by patching together template assembly blocks with filled in values, with a lot of INT instructions toward the quickbasic runtime, but it did compile, not interprete.

TIL! I had used qbasic back in school, but I somehow always assumed that these basics were interpreters.

QBasic was a slightly cut down version of Quickbasic that didn't include the compiler, so your assumption was correct in that case. QBasic was bundled with DOS but you had to buy Quickbasic.

Re: Python 3.13 Gets a JIT

#418
post #50
post #42

Earlier quoted context omitted.

when i wrote ur-scheme one of the surprising things i learned from it was that ahead-of-time compilation worked amazingly well for scheme. scheme is ruthlessly monomorphic but i was still doing a type check on every primitive argument i didn't realize they ever jitted newtonscript

NewtonScript 2.0 introduced a mechanism to manually JIT code, functions marked as native get compiled into machine code. Had the Newton not been canceled, probably there would be an evolution from that support. See "Compiling Functions for Speed" https://www.newted.org/download/manuals/NewtonToolkitUsersGu...

Note that interpreter in the Lisp world by default has a different meaning.

A "Lisp interpreter" runs Lisp source in the form of s-expressions. That's what the first Lisp did.

A "Lisp compiler" compiles Lisp source code to native code, either directly or with the help of a C compiler or an assembler. A Lisp compiler could also compile source code to byte code. In some implementations this byte code can be JIT compiled (ABCL, CLISP, ...).

The first Lisp provided a Lisp to assembly compiler, which compiled Lisp code to assembly code, which then gets compiled to machine code. That machine code could be loaded into Lisp and functions then could be native machine code.

The Newton Toolkit could compile type declared functions to machine code. That's something most Common Lisp compilers do, sometimes by default (SBCL, CCL, ... by default directly compile source code to machine code).

SBCL:

    * (defun add (a b) (declare (fixnum a b) (optimize (speed 3))) (+ a b))
    ADD
    * (disassemble #'add)
    ; disassembly for ADD
    ; Size: 104 bytes. Origin: #x7006E1789C                       ; ADD
    ; 89C:       0000018B         ADD NL0, NL0, NL1
    ; 8A0:       0A0000AB         ADDS R0, NL0, NL0
    ; 8A4:       E7010054         BVC L1
    ; 8A8:       BD2A00B9         STR WNULL, [THREAD, #40]        ; pseudo-atomic-bits
    ; 8AC:       BC7A47A9         LDP TMP, LR, [THREAD, #112]     ; mixed-tlab.{free-pointer, end-addr}
    ; 8B0:       8A430091         ADD R0, TMP, #16
    ; 8B4:       5F011EEB         CMP R0, LR
    ; 8B8:       E8010054         BHI L2
    ; 8BC:       AA3A00F9         STR R0, [THREAD, #112]          ; mixed-tlab
    ; 8C0: L0:   8A3F0091         ADD R0, TMP, #15
    ; 8C4:       3E2280D2         MOVZ LR, #273
    ; 8C8:       9E0300A9         STP LR, NL0, [TMP]
    ; 8CC:       BF3A03D5         DMB ISHST
    ; 8D0:       BF2A00B9         STR WZR, [THREAD, #40]          ; pseudo-atomic-bits
    ; 8D4:       BE2E40B9         LDR WLR, [THREAD, #44]          ; pseudo-atomic-bits
    ; 8D8:       5E0000B4         CBZ LR, L1
    ; 8DC:       200120D4         BRK #9                          ; Pending interrupt trap
    ; 8E0: L1:   FB031AAA         MOV CSP, CFP
    ; 8E4:       5A7B40A9         LDP CFP, LR, [CFP]
    ; 8E8:       BF0300F1         CMP NULL, #0
    ; 8EC:       C0035FD6         RET
    ; 8F0:       E00120D4         BRK #15                         ; Invalid argument count trap
    ; 8F4: L2:   1C0280D2         MOVZ TMP, #16
    ; 8F8:       0AFBFF58         LDR R0, #x7006E17858            ; SB-VM::ALLOC-TRAMP
    ; 8FC:       40013FD6         BLR R0
    ; 900:       F0FFFF17         B L0
    NIL
I've entered a function and it gets ahead of time compiled to non-generic machine code.

Calling the function ADD with the wrong numeric arguments is an error, which will be detected both a compile and at runtime.

    * (add 3.0 2.0)

    debugger invoked on a TYPE-ERROR @7006E17898 in thread
    #:
      The value
        3.0
      is not of type
        FIXNUM
      when binding A
Redefinition of + will do nothing to the code. The addition is inlined machine code.

Re: Python 3.13 Gets a JIT

#419
post #381

Earlier quoted context omitted.

Because it took 10 years to have Python 3 being as fast as Python 2 while being more strict. 2-9% means it will be another 10 years to have Python 3 being significantly faster. Ref: https://mail.python.org/pipermail/python-dev/2016-November/1...

5.5% compounded over 5 years is a bit over 30%: not a huge amount but an easily noticeable speed-up. What were you thinking of when you typed “significantly faster”?

Compunding a decrease works differently than an increase. If something gets 10% faster twice it actually got 19% faster. In other words, the runtime is 90% of 90%, i.e. 81%.

Re: Python 3.13 Gets a JIT

#420

It's interesting to see these 2-9% improvements from version to version. They are always talked about with disappointment, as if they are too small, but they also keep coming, with each version being faster than the previous one. I prefer a steady 10% per version over breaking things because you are hoping for bigger numbers. Those percentages add up!

This is happening mostly because Guido left, right? The take that CPython should be a reference implementation and thus slow always aggravated me (because, see, no other implementation can compete because every package depends on CPython kirks, in such a way that we're now removing the GIL of CPython rather than migrating to Pypy for example)

It's fascinating to me that this process seems to rhyme with that of the path PHP took, with HHVM being built as a second implementation, proving that PHP could be much faster -- and the main project eventually adopting similar approaches. I wonder if that's always likely to happen when talking about languages as big as these are? Can a new implementation of it ever really compete?
Post reply on HN