Taková zajímavost:
Myslel jsem, že nic jako JIT nebo Interpretovaný kód nemůže běžet rychleji než Cčko, ale údajně to možné je. Cčkový kód přeložený například v roce 2013 tak může běžet pomaleji, než Pythonový kód s chytrým načítáním a za použití instrukcí dostupných v roce 2023. Hodně by mě zajímalo, o kolik bude Python pomalejší, protože už teď jsou rozdíly často spíše menší (dle typu zátěže).
Tiez mi hlava nebrala, že interpretovaný (respektíve JIT-ovaný) kód môže bežať rýchlejšie, ako natívny. Čo mňa presvedčilo je toto: PGO (profile guided optimization). Ono keď človek skompiluje kód, ale nevie sa, ktorá cesta vo vetvení sa bude používať častejšie, alebo ktorá výnimka sa "nikdy" nevyhadzuje, tak sa to dá odJITovať efektívnejšie, ako statický preklad bez týchto informácií. Tieto informácie ale vie už dnes dodať PGO... Má to tedy efekt, keď dáta nevieme/nechceme získavať... (a asi i iné príklady sa dajú nájsť)
On stačí už jednoduchý příklad:
class A { void outer() { inner(); } virtual void inner(); } class B: A { virtual void inner(); }
Zatímco C++ má smůlu, bo u outer() neví, jak vypadá inner() a musí vygenerovat jump přes pointer v tabulce virtuálních funkcí, tak naopak JIT jazyk ví definice všech funkcí a může inlinovat bez omezení - a pro různé třídy může vygenerovat jiné outer optimalizované pro danou třídu.
LTO dokáže něco vyřešit, ale tohle zrovna asi ne (už proto, že ani v době linkování nemusí být všechny informace k dispozici - v případě knihoven nahrávaných za běhu nemožné).
Toto je ale z hlediska výkonu strašně nezajímavé - největěí rozdíl dnes dělá autovektorizace - takže optimalizace cyklů a ne nějakých volání funkcí. Na druhou stranu jo, pokud někdo napíše naprosto debilní kód, který v nějakém cyklu co má běžně třeba miliardu iterací a volá tam virtuální funkci, tak s tím autovektorizace nic neudělá a JIT toho může využít, ale toto je podle mě naprosto nepraktický příklad.
Ja som sa o tom, ze JIT moze byt richlejsi ako C-ecko presvedcil pred dvoma rokmi prepisom jednej serverovej aplikacie na .Net 6 a C#.
Vo vysledku to bolo o 10-15% richlejsie per request a priepustnost sa zdvihla dvojnasobne (to vdaka async/await). CPU to zralo rovnako a RAM konstane o 35-40MB viac a to aj pri zatazi.
čkový kód přeložený například v roce 2013
A není jednoduší si ten kód přeložit v roce 2023?
Podle mě aplikovat JIT na statický kód je úplná blbost. JIT se hodí nejvíc tam, kde se potřebuje zkompilovat kód, který v době překladu té aplikace nebyl známý, ale statický kód? JIT má většinou omezený čas, jednoduchý register allocator, atd... Stačí se podívat na to, kolik stojí v LLVM třeba zkompilovat jednu funkci - to může být třeba 100ms, toto je naprosto nevhodné pro JIT, takže JIT potřebuje udělat nějaký trade-off, aby se ta funkce zkompilovala třeba za 1ms, aby ta aplikace vůbec byla schopná v nějakém čase nastartovat. Jasně, může se např. kompilovat jen něco, a využít LLVM kvality jen pro kód, který je "hot", ale toto všechno jsou jen další implementační komplikace a je potřeba to potom celé nějak maintainovat (co je JIT, co je interpret, co je super fast JIT, atd...) - no a v konečném výsledku je takové řešení dobré jen pro microbenchmark, kde se právě zoptimalizuje ta hot sekce... ale komplexní aplikace je stále pomalá (hello, java...)
.Net to riesi tak, ze ma dvojurovnovy JIT, za tu 1ms skompiluje veci co treba na nastarovanie a pouzivanie. A nasledne na pozadi zacne kompilovat metody, ktore sa intezivne pouzivaju s vysokou optimalizaciou, sice to trva dlhsie, ale to nevadi lebo aplikacia uz bezi.
Prave na komplexnych aplikaciach vidiet, ze nativne kompilovany kod je len o par percent richlejsi (niekedy ani to nie), ako ten z modernym JIT-om.
tym ale nechcem povedat, ze vsetky aplikacie s JIT-om budu richlejsie alebo rovnako dobre ako nativne (napriklad taky pgAdmin, alebo veci napisane v Elektrone su vyslovene peklo).
21. 6. 2023, 07:26 editováno autorem komentáře
Nejen chyby, ale i nekompatibility mezi verzemi. Ještě před pár týdny pytorch nefungoval na 3.11, při pokusu rozchodit prakticky jakýkoli půl roku starý AI projekt si s láskou vzpomenu na devadesátky a tehdejší DLL Hell i přes důsledné používání venvu.
Pomalost je to poslední, co by mě na Pythonu (a hlavně ekosystému kolem) vadilo.