Conversation

Replying to
The inner contrarian in me wonders whether language design is due for a NetBurst moment when we all realize deep pipelines are bad and go back to simpler single pass compilable languages
13
33
Replying to
if we're talkin' strange timelines: ship everything at -O1 and have a JIT infrastructure that can build and drop in the -O3 version using runtime feedback on where dynamic calls land etc. (kinda like .NET NGEN, but starting from a language made for AOT)
1
Replying to and
Android has this kind of compilation stack for code targeting the Android Runtime (ART). Historically they moved from an interpreter to interpreter + JIT to near full AOT compilation (interpreter still used for one-time init and dynamic code) before arriving at the current model.
1
2
Replying to and
The JIT compiler can do some low-level tricks and optimizations that an AOT compiler cannot, so it still has a purpose once code has been AOT compiled. There are also a lot of options for configuring how this works. Can still use near full AOT compilation or full AOT compilation.
1
2
Replying to and
There's partial documentation on this here: source.android.com/devices/tech/d For example, I use the near full AOT compilation mode ('speed') without JIT or profiling: github.com/GrapheneOS/pla Full AOT compilation mode (disabling heuristics for interpreting cold code) is 'everything'.
1
Replying to and
They've also done some interesting optimizations, most of which I need to disable for my work. You may know that it spawns apps by forking from a Zygote acting as a template with the common classes / libraries already loaded and initialized, a preloaded OpenGL context and so on.
1
Replying to and
They also have some weird optimizations like shared RELRO sections and pre-generating the heaps for libraries, not just the code. I think the way it works is they load them up in a deterministic environment and then write out the heap in a way that's quick to verify on boot.
1
Replying to and
That sounds a lot like what Darwin does with the shared cache, to prelink the system dylibs into one image, pre-bind ObjC and Swift runtime data structures, etc., though we're starting from already native code
1
2
Replying to and
I have to drop most of this in order to have proper per-app ASLR and other probabilistic mitigations rather than shared bases and other secrets. It makes a big difference for app spawning time and also memory usage, since a lot of the initial heap in the Zygote remains the same.
1
Replying to and
Can see some of how they take advantage of the Zygote here: android.googlesource.com/platform/frame. This is run a single time on boot for each supported architecture. The image classes section in source.android.com/devices/tech/d explains that bit. For their use it only really optimizes Zygote start-up.
1
Show replies