Open markshannon opened 4 months ago
By my count we're currently hovering around 54% of code executed in tier two (our benchmarks run about 266 billion tier one instructions on normal builds and 122 billion instructions on JIT builds). I've identified a few strategies for improving this (based on stats and tracing through how we execute a bunch of the benchmarks) and will start landing PRs soon. No magic bullets here, just chipping away at things:
CALL_KW
and CALL_FUNCTION_EX
. We probably don't need to do anything too crazy here early on in terms of optimizing calls... we can start by just adding a handful of specializations that allow us to trace through them instead of ending the trace.CALL_LIST_APPEND
, IMPORT_NAME
, LOAD_NAME
, BUILD_SET
, SEND_GEN
, and IMPORT_FROM
), and some are harder (LOAD_ATTR_PROPERTY
, BINARY_SUBSCR_GETITEM
, CALL_ALLOC_AND_ENTER_INIT
, RAISE_VARARGS
, and BINARY_OP_INPLACE_ADD_UNICODE
).SEND_ASYNC_GEN_ANEXT
, using a similar shim frame as CALL_ALLOC_AND_ENTER_INIT
.DYNAMIC_EXIT
) or statically (by using the current stack when projecting to infer callers). A more radical idea could be to start recording traces instead of projecting them. That simplifies a lot of things, but is a big rewrite of some pretty core stuff.DEOPT_IF
s into EXIT_IF
s for better handling of control flow and polymorphism. _FOR_ITER_TIER_TWO
is an obvious candidate here, but there are others, too.My motivation for this is to make JIT improvements more pronounced. We currently spend less than 10% of our time in the JIT (vs ~25% of our time in tier one), which means that we need to improve the performance of JIT code by over 10% just to see a 1% improvement on the benchmarks. My (probably ambitious) goal is to get the fraction of code executed in tier two up to around 80% (meaning, in the neighborhood of 25%-30% of the total time spent running the benchmarks) in the next couple of weeks. Then the improvements can be easier to measure and iterate on.
It's also worth noting that our stats are currently broken on benchmarks that use C extensions or spawn subprocesses. So the actual numbers may vary a bit right now, but probably aren't heavily biased one way or another.
According to stats and profiling only about 40% of bytecode instructions are executed by tier 2 and the remaining 60% by tier 1.
We the expected improvements to the JIT and tier 2 optimizer we expect tier 2 (with JIT) to have a significantly faster than tier 1. It therefore make sense to get the fraction of instructions executed by tier 2 up from 40% to nearer 90%.
To do that we need to:
Linked PRs