Jenom mne vrta hlavou, jak je reseny garbage collector u procesoru pro javu. Je to soucast procesoru, nebo je to az soucasti programu nebo se na nejakou praci s pameti u takovychto procesoru kasle a pocita se s tim, ze se o to postara prekladac?
Alokátor paměti v Javě je strašně primitivní věc (mnohem jednodušší než C alokátor).
Zjednodušeně funguje asi tak, že máme dvě stejně velké oblasti a do jedné z nich ukazuje ukazatel. Při alokaci objektu o velikosti N se k ukazateli přičte N a vrátí se stará hodnota ukazatele --- čili ty objekty se tam skládají jeden za druhým.
Až se dojde na konec oblasti, tak se začne alokovat ve druhé oblasti a současně s tím se prochází dosažitelné objekty a ty se přesouvají z první do druhé oblasti. Až se všechny projdou, tak se první oblast celá uvolní --- ta pak čeká na použití, až se zase zaplácá druhá oblast).
Takže bych tipoval, že to bude tak, že alokace objektu bude v hardware a až ta oblast přeteče, tak to vyvolá nějaký exception. Ale detaily neznám.
A to je prave to co by me zajimalo - kdo nebo co je zodpovedny(e) za praci s pameti a jak je to technicky resene. Procesor je totiz relativne primitivni soucastka, co se tohoto tyce, ale v pripade javy by se mohlo neco takoveho vyplatit.
Hardwarovou podporu správy paměti měly už lispové procesory. To není nic tak složitého, ale je třeba si uvědomit, že tehdejší stroje byly často word-oriented a měly navíc tagovanou paměť... To odstraňuje spoustu problémů, které se dnes složitě řeší softwarově, jako jsou typové kontroly a optimalizace.
Dokonce víc než dvakrát. Leo Galamboš (dělá na MFF vyhledávač v javě) zjistil, že to sežere spoustu další paměti na kdovíco. Má počítač s 4GB, javě dal 2GB a navíc to vyžralo další necelý 1GB z neznámého důvodu.
První implementace javy (bez tohohle garbage collectoru, co současně i přesouvá a defragmentuje) žraly mnohem víc, prý tam jakýkoli objekt sežral asi 2kB.
Tak to muselo být nějaký úchylný. To už Lisp to měl dvacet let před Javou vyřešený líp, s MacLispem na PDP-10 podobný problémy určitě nebyly, kdepak dvě kila na objekt...
Chtelo by to mozna driv cist nez psat. Java ma opravdu 2 oblasti pro novy objekty, ale to zdaleka neni cela pamet. Jeden prazdny objekt sezere na mym compu 8 bajtu.
Jak funguje HW v java procesorech, netusim - ale zdaleka nemusi delat vsecko, alokace je trivialni, GC je slozity, jestli to nejak podporuje, nevim.
Nechápu, proč by nurseries mělo být víc, a už vůbec nechápu, co to má společného s čtením před psaním. :-) Přijde mi, že to může jedině zesložitit řešení write barriers v dalších generacích heapu, a ty by měly mít co nejmenší overhead. A osm bajtů je na 32b stroji celkem jasných - hlavička objektu a reference na třídu/typ.
pane boze - ty fseznalku - ses z MFF a pises sracky a domenky jak nakej podelanej pisalek z blesku - budto se vyjadruj uplne nebo vubec - neco nejaky nekde nejak slysel sem a mozna nejak na kdovico - a s toho vypliva ze zere 2x - tydle lidi mam rad
No, pokud vím, tak způsob práce s pamětí v Javě není předepsaný, a tenhle naivní kopírovací princip se určitě nepoužívá.
O Javě od Sunu se dá dočíst, že používá hybridní generační přístup: všechny objekty vznikají v Eden Space, když se ten zaplní, tak se živé objekty z něj a z jednoho Survivor Space přesunou do druhého Survivor Space (to je skoro to, co popisuješ, ale Survivor Spaces jsou oproti ostatním částem heapu velmi malé), a to se opakuje dokud nedojde místo i tam. Přičemž se počítá s tím, že velká většina objektů zanikne velmi brzy po svém vzniku, takže se nedostanou ani z Edenu. Přeživší objekty se pak přesouvají do Tenured Space, kde se pro čištění používá mark and sweep. V základu je to všechno Stop The World, existují i paralelní implementace. Jak se řeší zvětšování heapu netuším. U IBM to dělají zase nějak jinak (nevím jak).
To, co jsem popsal, pochází z nějakého popisu javy od IBM. Odtud plyne to známé ponaučení, že se nemá alokovat objekt v cyklu. Sunu asi došlo, že to plýtvá pamětí, a tak to vylepšil.
Když budeš alokovat objekt v cyklu, nic hrozného se nestane. Pokud na objekty nebude žádná reference zvenčí nursery, tak je systém šmahem zahodí s minimální vynaloženou prací. Navíc nursery má dobrou cache locality, je obvykle docela malá. Ty alokace skutečně nemusejí být drahé, alespoň ne v porovnání s mallocem. Samozřejmě že nealokovat vůbec a mít všechno, co se zpracovává najednou, hezky při sobě, jak je to v Cčku nebo ve Forthu celkem běžné, je nejlepší alternativa, pokud je to z povahy problému možné, ale pokud člověk potřebuje náhodné alokace (třeba na obecné stromy s různými typy a velikostmi uzlů a tak), nemyslím, že by na tom malloc a free byly nějak líp - tedy aspoň ne normální malloc a free. Řekl bych, ře dobře napsaná Cčková aplikace bude rychlejší než aplikace v Javě právě tehdy, pokud bude mít citlivě navrženou práci s pamětí a nebude moc cvičit malloc, protože hodně dynamická správa paměti asi nebude silná stránka Cčka (nepoužije li člověk libgc nebo něco podobného).
A jak už jsem psal, recyklovat objekt místo vytvoření nového stylem "změním jednu referenci ve starém objektu, aby ukazovala na nový, co teď právě vytvářím" může oproti vytvoření nového objektu vyjít v Javě nebo Lispu (s generačním GC) překvapivě draho. Aby správce paměti dokázal vysledovat reference na objekty v nursery (které je nutné časem přemístit), jsou nad objekty v "dynamické části heapu" (druhá generace a i ty další) nasazené write barriers, protože správce paměti musí reference vedoucí do nursery sledovat.
Zakladni podpora pro multithreading a sberac smeti je opravdu implementovana uz v procesoru, viz http://www.cs.ualberta.ca/~macg/C429/Extras/picoJava.htm Detaily moc neznam (Sun jaksi picoJavu nedokazal protlacit na trh), ale predpokladam, ze tam stejne jako normalne pobezi uklizeci vlakno, ktere s podporou procesoru bude pamet cistit (resp. to cisteni je zNULLovani par ukazatelu, pardon referenci :-)
Prekladac se o to postarat v mnoha pripadech nemuze, je to veci runtime.