Pudl bude zakopaný v tom, že ty benchmarky jsou malé, jednoúčelové a vysoce optimalizované prográmky. Pokud by se člověk pokusil přepsat do C nebo Rustu nějakou větší aplikaci, tak nejen že to bude mnohem náročnější na údržbu, ale nejspíš ani to zlepšení energetické efektivity nebude tak zázračné.
A pak by se mělo započítat i to o kolik víc energie spálí programátor při vývoji a debugovaní v nízkoúrovňovém jazyce :-)
Neříkám, že je problém napsat velkou aplikaci v nízkoúrovňovém jazyce. Jen že to je víc kódu. A čím víc kódu, tím víc tam bude funkcí, které by zvládl optimalizovat i vysokoúrovňový jazyk (protože málokterá aplikace je celá CPU-heavy), takže ten rozdíl v efektivitě může vyjít úplně jinak než u malého benchmarku.
Praktický příklad, kde na jedné straně bude (předem kompilovaný do nativního kódu*) Rust a na druhé straně jiný jazyk s JITem, který bude při dlouhém běhu a dostatku RAM rychlejší, z fleku nevytáhnu. Nabízí se ale jiná zajímavá srovnání:
a. GraalVM JIT vs. native-image. Máme srovnání stejného se stejným, jednou JIT, jednou kompletní překlad před spuštěním. JIT žere víc RAM a spuštění trvá déle, ale jakmile máme spuštěno a zahřáto, typicky je to rychlejší než native-image.
b. Teoreticky bychom podobné srovnání mohli udělat i pro Rust, protože GraalVM umí LLVM (Sulong). Takže bychom mohli mít Rust s low-level JITem. Prakticky tu může být více problémů a neznámých, a přecejen Sulong – jakkoli je zajímavý – asi nebude tím hlavním tahounem GraalVM.
EDIT: Důvod, proč JIT může být rychlejší, je, že JIT si může dovolit dělat i různé spekulativní optimalizace (pokud optimalizace selže, může to deoptimalizovat a klidně zkompilovat znovu) a statistiky za běhu.
*) Obecně to není jediná možnost u Rustu, ale tiše jsem předpokládat, že to máte na mysli.
27. 2. 2022, 00:17 editováno autorem komentáře
Co myslíte tím „v praxi“?
a Najdete-li vhodnou aplikaci kompatibilními s native-image, můžete porovnat AOT a JIT celkem snadno. Není to Rust, ale je to srovnávání srovnatelného.
b. Myslím, že kdybych tomu věnoval pár hodin, najdu případ, kdy Rust pod Sulongem bude výkonnější díky JIT, i kdyby jinak byl Sulong pomalejší než LLVM. (Nevím, jak si proti sobě stojí.) Ale byl by to syntetický benchmark…
c. Nejvíc „v praxi“ by to bylo na reálných aplikacích, ale tak je dost problém srovnávat srovnatelné. Najdete dvě aplikace, jedna v Rustu, druhá třeba v Javě, každá bude dost možná napsaná úplně jinak (zvlášť bude-li to netriviální aplikace) atd. Ve výsledku by za tím rozdílem mohlo stát něco úplně irelevantního.
Juliu moc neznám, IIRC má dynamické typy. Tím spíš ale potřebuje JIT, aby byla Rustu vůbec konkurenceschopná. Při AOT kompilaci by kompilátor věděl dost málo o konkrétních typech, a bez toho lze ten kód přeložit dost genericky, třeba u operace + nebude jasné, jestli jde o součet celých čísel, floatů, nějaký mix, nebo třeba spojení řetězců. Samozřejmě, může to odvodit pro některé specifické případy, ale obecně ne. A kdyby to měl odvozovat obecně pro hromadu případů, generoval by obrovský kód, a stejně by to nejspíš bylo málo.
To samo o sobě ale jen říká, že Julia potřebuje JIT, aby mohla s Rustem vůbec soupeřit, nevysvětluje, jak může Rust předehnat. To bych hledal ve spekulativních optimalizacích, kde JIT může třeba volání virtuální metody přeložit jako statický dispatch, a teprve v případě potřeby z toho udělat dynamický dispatch. Nevím, jestli zrovna toto bude nejčastější problém v Rustu, je to spíše ukázka, kde JIT může nabrat výhodu.
Ne, v Julii není mezi AOT a JIT vůbec žádný rozdíl, viz “type stability”. A protože má multimetody, všechna volání funkcí se škatulkují už při (prvním) překladu ve všech případech. Má hodně silný typový systém s abstraktními, generickými a součtovými typy, takže informací k tomu má dostatek. Pro překlad používá LLVM a jeho optimalizace. Prostě funguje úplně jinak, než Java (mnohem lépe).