I compilatori hanno bisogno di due cose per generare codice performante: informazioni e risorse.
I compilatori JIT hanno a disposizione molte più informazioni dei compilatori AOT. L'analisi statica è impossibile nel caso generale (quasi tutto ciò che vorresti sapere su un programma può essere ridotto al problema di stallo o al teorema di Riso), e difficile anche nel caso particolare. I compilatori JIT non hanno questo problema: non devono analizzare il programma in modo statico, possono osservarlo dinamicamente in fase di runtime.
Inoltre, un compilatore JIT dispone di tecniche a disposizione dei compilatori AOT, il più importante è la de-ottimizzazione. Ora, potresti pensare che la de-ottimizzazione è importante per le prestazioni? Bene, se si può de-ottimizzare, allora si può essere eccessivamente aggressivi nel fare ottimizzazioni che sono effettivamente non valide (come inline una chiamata al metodo che può essere o meno polimorfa), e se si scopre che si è sbagliato, è possibile quindi de-ottimizzare di nuovo al caso non inline (per esempio).
Tuttavia , c'è il problema delle risorse: un compilatore AOT può impiegare tutto il tempo che vuole e utilizzare tutta la memoria che vuole. Un compilatore JIT deve rubare le sue risorse dal vero programma che l'utente vuole usare adesso .
Normalmente, questo non è un problema. Le nostre macchine di oggi sono così ridicolmente sopraffatte, che ci sono sempre abbastanza risorse a disposizione della JIT. Soprattutto perché il JIT utilizzerà la maggior parte delle risorse quando viene introdotto un sacco di nuovo codice nel sistema in una volta, che di solito è durante l'avvio del programma o quando il programma passa da una fase all'altra (ad esempio dall'analisi dei file di configurazione all'impostazione del oggetto grafico, o dalla configurazione di finitura per avviare il lavoro effettivo), in quali momenti il programma stesso di solito non utilizza ancora molte risorse (specialmente durante l'avvio del programma). L'Azul JCA è un buon esempio. Ha 864 core e 768 GiByte RAM nella sua configurazione più grande (e si noti che non sono stati venduti per un bel po 'di tempo, quindi è in realtà una tecnologia vecchia di parecchi anni). Secondo le misure di Azul, il JIT utilizza forse 50 core, quando sta lavorando molto duramente. Sono ancora oltre 800 core rimasti per il programma, il sistema e il GC.
Ma il tuo tipico dispositivo Android non ha 1000 core e un TiByte di RAM. Ed è estremamente interattivo e sensibile alla latenza, quando l'utente inizia, ad esempio, WhatsApp, vuole scrivere un messaggio giusto ora. Non in 500 msec, quando la JIT si è riscaldata. ora .
Questo è ciò che rende attraente AOT qui. Si noti inoltre che la compilazione JIT non solo ruberà risorse dal programma in esecuzione, ma avrà anche bisogno di alimentazione a batteria, e avrà bisogno di ogni tempo di esecuzione del programma, mentre un compilatore AOT dovrà solo spendere quel budget energetico una volta, quando l'app è installata.
Potresti andare ancora più estremo e inviare la compilation all'app store o anche allo sviluppatore, come Apple, ma Apple ha il vantaggio di un insieme molto più limitato di possibili piattaforme di destinazione da considerare, quindi su dispositivo La compilazione di AOT sembra un compromesso ragionevole per Android.