Python si získal pověst výkonného, flexibilního a snadno použitelného jazyka. Tyto přednosti vedly k jeho používání v obrovské a stále rostoucí škále aplikací, pracovních postupů a oborů. Ale konstrukce jazyka – jeho interpretovaná povaha a dynamika běhu – znamená, že Python byl vždy řádově pomalejší než strojově nativní jazyky jako C nebo C++.
V průběhu let přišli vývojáři s řadou řešení, jak omezení rychlosti Pythonu obejít. Například můžete psát výkonově náročné úlohy v jazyce C a obalit je jazykem Python; mnoho knihoven pro strojové učení dělá přesně toto. Nebo můžete použít Cython, projekt, který umožňuje posypat kód Pythonu informacemi o běhovém typu, které umožňují jeho kompilaci do jazyka C.
Obešlapaná řešení však nikdy nejsou ideální. Nebylo by skvělé, kdybychom mohli vzít existující program v Pythonu tak, jak je, a spustit ho dramaticky rychleji? Přesně to umožňuje PyPy.
PyPy vs. CPython
PyPy je kapkovitá náhrada za standardní interpret jazyka Python, CPython. Zatímco CPython kompiluje Python do mezikódu bytecode, který je pak interpretován virtuálním strojem, PyPy používá kompilaci JIT (just-in-time) k překladu kódu Pythonu do strojově nativního jazyka assembleru.
V závislosti na prováděné úloze může být nárůst výkonu dramatický. V průměru PyPy zrychluje Python přibližně 7,6krát, přičemž některé úlohy se zrychlují 50krát a více. Interpret CPythonu jednoduše neprovádí stejné druhy optimalizací jako PyPy a pravděpodobně je ani nikdy provádět nebude, protože to není jedním z cílů jeho návrhu.
Nejlepší na tom je, že k odemknutí zisků, které PyPy poskytuje, není zapotřebí téměř žádné úsilí ze strany vývojáře. Stačí vyměnit CPython za PyPy a z větší části máte hotovo. Existuje několik výjimek, které jsou popsány níže, ale deklarovaným cílem PyPy je spustit existující, nemodifikovaný kód Pythonu a poskytnout mu automatické zvýšení rychlosti.
PyPy v současné době podporuje Python 2 i Python 3, a to prostřednictvím různých inkarnací projektu. Jinými slovy, musíte si stáhnout různé verze PyPy v závislosti na verzi Pythonu, kterou budete používat. Větev PyPy pro Python 2 existuje mnohem déle, ale verze Python 3 byla aktualizována až v poslední době. V současné době podporuje jak Python 3.5 (produkční kvalita), tak Python 3.6 (beta kvalita).
Kromě podpory všech základních jazykových verzí Pythonu pracuje PyPy s naprostou většinou nástrojů v ekosystému Pythonu, například pip
pro balíčkování nebo virtualenv
pro virtuální prostředí. Většina balíčků jazyka Python, dokonce i ty s moduly jazyka C, by měla fungovat tak, jak je, i když existují omezení, která rozebereme níže.
Jak funguje PyPy
PyPy používá optimalizační techniky, které se vyskytují v jiných just-in-time kompilátorech pro dynamické jazyky. Analyzuje běžící programy v jazyce Python a zjišťuje typové informace objektů při jejich vytváření a používání v programech a poté tyto typové informace používá jako vodítko pro zrychlení práce. Pokud například funkce jazyka Python pracuje pouze s jedním nebo dvěma různými typy objektů, PyPy vygeneruje strojový kód, který tyto specifické případy zvládne.
Optimalizace PyPy jsou prováděny automaticky za běhu, takže jeho výkon zpravidla nemusíte nijak upravovat. Pokročilý uživatel může experimentovat s volbami příkazového řádku PyPy a generovat rychlejší kód pro speciální případy, ale jen zřídka je to nutné.
PyPy se také odchyluje od způsobu, jakým CPython zpracovává některé vnitřní funkce, ale snaží se zachovat kompatibilní chování. PyPy například zachází se sběrem odpadu jinak než CPython. Ne všechny objekty jsou po opuštění oboru okamžitě posbírány, takže program Python spuštěný pod PyPy může vykazovat větší paměťovou stopu než při spuštění pod CPythonem. Stále však můžete používat vysokoúrovňové ovládací prvky kolekce odpadu v jazyce Python vystavené prostřednictvím modulu gc
, například gc.enable()
, gc.disable()
a gc.collect()
.
Pokud chcete získat informace o chování JIT v PyPy za běhu, PyPy obsahuje modul pypyjit
, který vystavuje mnoho háčků JIT pro vaši aplikaci v Pythonu. Pokud máte funkci nebo modul, který se zdá, že se s JIT chová špatně, pypyjit
vám umožní získat o něm podrobné statistiky.
Další modul specifický pro PyPy, __pypy__
, vystavuje další funkce specifické pro PyPy, takže může být užitečný při psaní aplikací, které tyto funkce využívají. Vzhledem k dynamice běhu Pythonu je možné sestavit aplikace Pythonu, které tyto funkce využívají, když je PyPy přítomen, a ignorují je, když přítomen není.
Omezení PyPy
Jakkoli se PyPy může zdát magický, není to magie. PyPy má určitá omezení, která snižují nebo znemožňují jeho účinnost pro určité druhy programů. Bohužel PyPy není zcela univerzální náhradou za základní běhové prostředí CPython.
PyPy funguje nejlépe s aplikacemi v čistém Pythonu
PyPy vždy fungoval nejlépe s „čistými“ aplikacemi v Pythonu – tj. aplikacemi napsanými v Pythonu a ničím jiným. Balíčky Pythonu, které spolupracují s knihovnami C, jako je NumPy, si nevedly tak dobře kvůli způsobu, jakým PyPy emuluje nativní binární rozhraní CPythonu.
Vývojáři PyPy tento problém vyřešili a zajistili větší kompatibilitu PyPy s většinou balíčků Pythonu, které závisí na rozšíření C. Například Numpy nyní s PyPy funguje velmi dobře. Pokud ale chcete maximální kompatibilitu s rozšířeními jazyka C, použijte CPython.
PyPy nejlépe pracuje s déle běžícími programy
Jedním z vedlejších efektů toho, jak PyPy optimalizuje programy v Pythonu, je, že z jeho optimalizací nejvíce těží déle běžící programy. Čím déle program běží, tím více informací o typech za běhu může PyPy shromáždit a tím více optimalizací může provést. Jednorázové skripty v jazyce Python nebudou mít z takovýchto věcí prospěch. Aplikace, které z toho mají prospěch, obvykle obsahují smyčky, které běží po dlouhou dobu, nebo běží nepřetržitě na pozadí – například webové rámce.
PyPy neprovádí kompilaci v předstihu
PyPy kompiluje kód Pythonu, ale není to kompilátor kódu Pythonu. Vzhledem ke způsobu, jakým PyPy provádí optimalizace, a k inherentní dynamičnosti jazyka Python neexistuje způsob, jak výsledný kód upravený JITem emitovat jako samostatnou binárku a znovu ji použít. Každý program musí být zkompilován pro každé spuštění. Pokud chcete Python zkompilovat do rychlejšího kódu, který lze spustit jako samostatnou aplikaci, použijte Cython, Numba nebo v současnosti experimentální projekt Nuitka.