• lobsters__mira@crustaceanson.theshelf.top
      link
      fedilink
      arrow-up
      0
      ·
      edit-2
      13 days ago

      Python is rather dynamic and therefore by default needs to do a lot of work to traverse hierarchies of objects, do dict lookups, check when it needs to invoke getters/setters etc - where a more static language like Java would just perform an access to a fixed offset. I do not know how optimized this currently is, hopefully somebody with more up to date knowledge of cpython could explain?

      That all that is not just slow on its own, but prevents further optimizations like inlining. JITs get around this problem by observing what actual the behavior of the code is, and e.g. compiling an optimized version of a piece of code for a specific combination of types.

      I don’t know if it’s still the current approach, but iirc cpython’s JIT was based on pattern matching on the code and emiting premade machine code. That get’s rid of bytecode instruction dispatch overhead (which wasn’t a big part of the overhead in the first place), but not a ton more.

      Take that with a teaspoon of salt though, I haven’t taken a proper look at cpython.


      score 3 · canonical

        • lobsters__mira@crustaceanson.theshelf.top
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          13 days ago

          It explains why a jit for Python, Ruby, JS & co that wants to produce performant code has to take advantage of the fact that programs are less dynamic that what each piece of code permits per language semantics – code doesn’t get run with new types/values/environment every time.

          And yjit does in fact do this, via what they call lazy basic block versioning: When a basic block is is to be executed, yjit can produce a version of that block specialized for the types involved.


          score 1 · canonical