GC v Javě a Go

Zdenek Henek nereg

Re:GC v Javě a Go
« Odpověď #15 kdy: 04. 02. 2016, 00:34:26 »
Nevhodne nakladani s pameti zpusobuje presne, co jste popsal. Immutable objekty, zpracovani velkeho mnozstvi dat ve streamu by mohlo pomoct.

Není naopak naprosto obráceně lepší se těch immutable objektů zbavit? Mít jeden objekt který mění vnitřní stav je přeci pro GC mnohem lepší než pořád vytvářet nové immutable objekty!

Jedine pokud ten objekt, ktery meni stav se nedostane ven z funkce resp. vlakna. Jak se projekt rozrusta, tak se lokalni promena zacne zapisovat do cache atd.

Cokoliv, co je sdilene mezi vlakny - vyuziva cache nebo treba i jen session. Pokud je takovyto objekt sdileny tak mate problem napr. v transakcich, synchronizaci etc. Immutable objekt tento problem nemusi resit.

Tech vytvarenych objektu je naopak mene. Pokud menim immutable objekt (s pouzitim builder objektu), tak se vytvori tyto objekty:
builder a prevezme cleny z immutable objektu, ta cast, kterou je potreba zmenit a vysledny novy immutable objekt.
Pokud chci udelat zmenu objektu, ktery neni immutale, tak abych neovlivnil existujici objekt, tak musim udelat clone. To znamena vytvorit kopie uplne vseho bez ohledu na to, co budu menit. Pocitejte s tim, ze budete narazet na kod:

objekt = objekt.clone()
metoda(objekt)

a ve funkci metoda(objekt){
objekt = objekt.clone()
....
}

protoze si nebudete casem jisti, jestli vse co vola funkci metoda udelalo clone pred zavolanim funkce metoda a protoze je mozne vsechno menit vsude, tak to taky budete delat.

immutable objekty vypadji jako nanic, nez se dostanete k reseni podivnych chyb zpusobenych problemy se synchronizaci a kdyz se pokusite vyuzit distribuovane cache cely problem ziskava novy rozmer :)

Jestli chcete priklady, tak treba Date mel byt immutable, formatter taky, u Stringu se nikdo nepozastavi nad tim, ze je immutable.

Kolikrat jste uz videl toto?
public class Constants {
    public static final SimpleDateFormat date = new SimpleDateFormat("dd.MM.yyyy");
}

Prepis kodu, ktery vyuziva "mutanty" na kod, kde se vyuzivaji immutable objekty je ocistec a rewrite byl nakonec lepsi volba.


Kolemjdoucí

Re:GC v Javě a Go
« Odpověď #16 kdy: 04. 02. 2016, 00:36:23 »
Nevhodne nakladani s pameti zpusobuje presne, co jste popsal. Immutable objekty, zpracovani velkeho mnozstvi dat ve streamu by mohlo pomoct.

Není naopak naprosto obráceně lepší se těch immutable objektů zbavit? Mít jeden objekt který mění vnitřní stav je přeci pro GC mnohem lepší než pořád vytvářet nové immutable objekty!
Funkcionální struktury jsou často lepší. "Vnitřní stav" může být často dost divoký.

Záleží na definici pojmu "lepší". Faktem zůstává že funkcionální přístup často velmi zatěžuje GC, což v konečném důsledku má velmi negativní vliv na výkon. Programátoři ze staré školy (před používáním GC) kteří dokáží ukočírovat vnitřní stav objektů pak dodávají mnohem výkonnější řešení!

Zdenek Henek nereg

Re:GC v Javě a Go
« Odpověď #17 kdy: 04. 02. 2016, 00:38:48 »
Nevhodne nakladani s pameti zpusobuje presne, co jste popsal. Immutable objekty, zpracovani velkeho mnozstvi dat ve streamu by mohlo pomoct.

Není naopak naprosto obráceně lepší se těch immutable objektů zbavit? Mít jeden objekt který mění vnitřní stav je přeci pro GC mnohem lepší než pořád vytvářet nové immutable objekty!

Z pohledu GC je mnohem lepsi objekt, ktery chcipne driv, nez se dostane z edenu nebo objekt, ktery zije hodne dlouho - kdyz uz to musi byt. GC edenu je rychle a levne. GC tenured je to, co zpusobuje casem full gc a zastaveni na nekolik sekund.

Kolemjdoucí

Re:GC v Javě a Go
« Odpověď #18 kdy: 04. 02. 2016, 01:00:23 »
Nevhodne nakladani s pameti zpusobuje presne, co jste popsal. Immutable objekty, zpracovani velkeho mnozstvi dat ve streamu by mohlo pomoct.

Není naopak naprosto obráceně lepší se těch immutable objektů zbavit? Mít jeden objekt který mění vnitřní stav je přeci pro GC mnohem lepší než pořád vytvářet nové immutable objekty!

Jedine pokud ten objekt, ktery meni stav se nedostane ven z funkce resp. vlakna.

Aha, takže "jenom" ve většině případů? Pochopení tohoto je klíčem k pochopení toho proč jsou čistě funkcionální jazyky naprosto nepoužitelné pokud je potřeba brát ohled na výkon!

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:GC v Javě a Go
« Odpověď #19 kdy: 04. 02. 2016, 04:12:38 »
Nevhodne nakladani s pameti zpusobuje presne, co jste popsal. Immutable objekty, zpracovani velkeho mnozstvi dat ve streamu by mohlo pomoct.

Není naopak naprosto obráceně lepší se těch immutable objektů zbavit? Mít jeden objekt který mění vnitřní stav je přeci pro GC mnohem lepší než pořád vytvářet nové immutable objekty!
Funkcionální struktury jsou často lepší. "Vnitřní stav" může být často dost divoký.

Záleží na definici pojmu "lepší". Faktem zůstává že funkcionální přístup často velmi zatěžuje GC, což v konečném důsledku má velmi negativní vliv na výkon. Programátoři ze staré školy (před používáním GC) kteří dokáží ukočírovat vnitřní stav objektů pak dodávají mnohem výkonnější řešení!
V Javě jo, ale v jazyce se slušnou escape analýzou se většina objektů do GC vůbec nedostane. Přinejmenším ve standardní knihovně bývá práce s pamětí často velmi efektivní (to se týká i Swiftu, kde takto zase odpadá počítání referencí).


Sten

Re:GC v Javě a Go
« Odpověď #20 kdy: 04. 02. 2016, 05:21:13 »
Mám dotaz, na který se mi nepovedlo vygooglit odpověď: Proč je latence GC v Go o tolik menší než v Javě? Při velké haldě (nad řekněme 16GB) se Java zasekává na vteřiny, kdežto Go zamrzne jen na pár milisekund. Cvičně jsem nahrál do paměti celou naši firemní databázi (přes 10 GB) a při práci s vše jede Go hladce, zatímco Java "stops the world". Testováno na Linuxu, Java je od Oraclu, Go verze 1,5.
Java má zásadní problém, že vše alokuje na haldě. V Go vzniká z principu mnohem méně odpadu a ve spojení s kvalitním (tricolor) GC se ta troška uklidí rychle. ObjC také mělo podobně kvalitní tracing GC, než zavedli ARC, jež mimochodem slouží stejně dobře.

Java má pro lokální proměnné stack. Instance objektů se tam neukládají, ale používají se lokální reference, které se velmi rychle uklidí při ukončení metody, aniž by to muselo projít přes GC. (Pokud tyhle objekty obsahují instance jiných objektů, tak ty jsou alokované na haldě globálními referencemi, ale pochybuji, že by v Go existoval algoritmus, který by se tomu dokázal vyhnout. Takové alokace jsou běžně i v C++, ale tam to dost řeší RAII.)

CMS v Javě je taky tricolor, protože to je podstata paralelního mark+sweep.

Zdenek Henek nereg

Re:GC v Javě a Go
« Odpověď #21 kdy: 04. 02. 2016, 08:55:15 »
Pro javu existuji i alternativni jvm.
Napriklad Azul ma jvm, ktera pouziva tento gc https://www.azul.com/resources/azul-technology/azul-c4-garbage-collector/

Pouzivate to nekdo?

andy

Re:GC v Javě a Go
« Odpověď #22 kdy: 04. 02. 2016, 10:51:53 »
https://www.youtube.com/watch?v=aiv1JOfMjm0

a btw java ma tiez escape analysis, ale nie compile time.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:GC v Javě a Go
« Odpověď #23 kdy: 04. 02. 2016, 22:53:57 »
https://www.youtube.com/watch?v=aiv1JOfMjm0

a btw java ma tiez escape analysis, ale nie compile time.
Escape analýza v Javě je dost mizerná. Možná ji v deváté verzi vylepší, ale zatím jim moc nefunguje (v porovnání třeba s Go, ale i C#).