Do jaké míry je počítání referencí v Pythonu optimalizované? Mají tam sofistikované optimalizace ve spojení s CoW (ve stylu swiftího isKnownUniquelyReferenced) a statickou analýzu eliminující nadbytečné aktualizace čítače referencí (jako v LLVM)? Například OCaml chce vylepšit (zefektivnit) správu paměti, proto plánují opustit tracing GC. Podobné trendy v Pythonu?
22. 12. 2020, 13:00 editováno autorem komentáře
No prakticky žádné optimalizace se v klasickém CPythonu neprovádí. Nemáme ani obdobu TLAB ani paralelní GC ve stylu Shenandoah. Osobně by se mi líbílo mít možnost GC kompletně vypnout, a to včetně počítání referencí (to je ovšem řešeno makry, takže asi jen rekompilací Pythonu) - pro krátkou dobu běžící skripty by mi velký heap ani nevadil (popravdě tak velký nebývá - tisíce objektů max typicky, méně než u JVM při bootu).
(na druhou stranu se alespoň vyřešilo uvolňování objektů s redeklarovanou metodou __del__).
S tím opuštěním tracing GC mě to tedy překvapuje. Osobně si myslím, že správa paměti by neměla zpomalovat výpočetní vlákna, takže počitadla referencí jsou z tohoto pohledu dost zlo (zámky atd.). A zrovna rozumně navržený vícegenerační tracing GC je ověřené řešení. Zajímavé by možná byla nějaká detekce, jestli jsou reference z jednoho vlákna a ty atomické čítače nahradit normálními čítači (to by mohlo vyhovovat třeba pro 99% případů a ten zbytek by holt byl lockovaný).
Na AMD64 a ARM64 atomické aktualizace nejsou pomalejší (historicky to býval problém na MIPSu nebo PowerPC). Nicméně hlavní přínos moderních přístupů k RC je to, že statická analýza eleminuje většinu aktualizací úplně (protože nejsou potřebné) a hodně alokací se děje na zásobníku (díky escape analýze, to se používá i pro tracing GC, například v Go to hodně pomáhá). Čítač referencí dříve obnášel paměťovou režii, ale moderní 64-bitové architektury k tomu využívají tagged pointers, takže všechny (domnělé i skutečné) nevýhody a výhrady k RC na moderních CPU padají. Kdysi jsem si ze zvědavosti porovnal historii aktualizací čítače referencí v původním ObjC (z časů OpenStepu) a moderního ARC, statická analýza vyhodí 90% aktualizací a escape analýza flákne více jak polovinu objektů na zásobník (protože jsou "short-lived" a nemusí se pro ně alokovat místo na haldě), takže i kdyby ty zámky byly pomalé, tak jich moc nebude. Podobně dopadlo porovnání GC v Go a Javě, prvně jmenované cpe vše, co se dá, na zásobník, takže samotný GC nemá moc práce. K tomu ARC byly pěkné přednášky na WWDC před několika lety. Apple si prostě experimentálně ověřil, že počítání referencí je efektivnější, a teď k tomu došli i tvůrci OCamlu (někde na Leopardu měl OS X - tehdejší název macOS - i tracing GC pro aplikace nad Cocoa, Apple jej používal ve svých aplikacích, ale s příchodem iPhonu, který měl nejprve jen 128 MB RAM, tracing GC zahodili a vrátili se k RC).
23. 12. 2020, 00:35 editováno autorem komentáře
V CPythonu prakticky žádná větší escape analýza není. Existuje jen peephole optimizer transformující bajtkód a potom https://fatoptimizer.readthedocs.io/en/latest/ s jiným zaměřením.
Ovšem PyPy už je na tom mnohem lépe, jak díky optimalizacím nad AST, tak i kvůli jinak pojatému GC (https://rpython.readthedocs.io/en/latest/garbage_collection.html#garbage-collection), který vlastně pracuje na principu plug&play (GC lze vyměnit, to u CPythonu nejde).
PS: snad si najdu čas o PyPy napsat článek z pohledu použitých technologií.
Vytvořím objekt x=5. příkaz sys.getrefcount(x) vrátí hodnotu mnohem větší, než dvě. Např 147. Proč?
Jirka21
Ta pětka bude používaná na dost místech. Když je immutable, není důvod mít pro každé použití extra instanci. (Nebo jinými slovy - žádný objekt jsi nevytvořil, jen přiřadil do `x` již existující objekt.)
Internet Info Root.cz (www.root.cz)
Informace nejen ze světa Linuxu. ISSN 1212-8309
Copyright © 1998 – 2021 Internet Info, s.r.o. Všechna práva vyhrazena.