|
|
|
|
|
by zdragnar
1040 days ago
|
|
Does this mean the JIT engine will be compiling code that it would not have otherwise? That in itself might end up being a small penalty, given that so much code is never a hot path anyway. If not, I'm not seeing the type annotation adding value that the engine doesn't already have from existing runs. |
|
1. JIT sees a function take a lot of objects {x: int, y: int}
2. JIT compiles a hot path of that function for {x: int, y: int}
3. JIT sees an object of {x: int, y: int, z: int}, goes to a slow uncompiled (deoptimized) path of that function
4. Over time JIT sees a bunch more of {x: int, y: int, z: int} and compiles a hot path for that function
5. Over time the JIT sees that the compiled hot paths of {x: int, y: int} and {x: int, y: int, z: int} share a bunch of code and get called roughly evenly and further compiles an even more optimized shared hot path of {x: int, y: int, z?: int}
Note that this isn't the case in every JIT, or every runtime and mileage always varies when talking about JIT optimizations, but that's a roughly common way to look at that.
In theory, knowing ahead of time that expected/preferred shape is {x: int, y: int, z?: int}, the JIT could skip steps 1-4, start from step 5, just one "perfect" hot path for the most common expected object shapes, and see fast code for every {x: int, y: int} and {x: int, y: int, z: int} object the function takes, right from "the beginning" of run time.
(It might still fall back to a deoptimized path for a strange, rare {x: string, y: int} or something like that, but it still has a better hot path for what should be the more common/likely arguments. Which is why worst case and possibly average case having type knowledge doesn't perform better than existing JITs. But it can still enhance the best case.)
(ETA: Of course, Step 0 is determining that function is on a hot path in the first place. That is assumed to be the same in both cases with/without type information.)