Omezení alokace paměti

Embedder

Omezení alokace paměti
« kdy: 12. 03. 2018, 17:30:23 »
Jde nějak omezit alokace paměti na haldě, případně zcela obejít? Některé jazyky jsou efektivnější, protože umožňují alokaci na zásobníku, která je velmi levná a nepotřebuje GC (např. C++ nebo Go nebo Swift oproti Javě). Navíc existují i jazyky (a coding guidelines pro C(++)), které dynamickou alokaci nemají/zakazují. Proč teda Java vše alokuje dynamicky, takže každý objekt musí být uvolněn GC?


gll

  • ****
  • 429
    • Zobrazit profil
    • E-mail
Re:Omezení alokace paměti
« Odpověď #1 kdy: 12. 03. 2018, 17:54:43 »
Java ukládá lokální proměnné primitivních typů na stacku. Objekty jsou alokovány dynamicky pravděpodobně kvůli jednoduchosti. Nemusíš řešit reference a dereference. Řešíš nějaký konkrétní problém, kde to vadí?

Jester

Re:Omezení alokace paměti
« Odpověď #2 kdy: 12. 03. 2018, 18:57:59 »
nějaký konkrétní problém, kde to vadí?
Na to stačí při překladu v kódu v Go nechat si vypsat escapované proměnné, člověk jen zírá, co všechny jazyky jako Java hází zbytečně na haldu.

Jinak s tím Swiftem to pravda není, třídy jdou všechny na haldu.

Re:Omezení alokace paměti
« Odpověď #3 kdy: 12. 03. 2018, 19:11:44 »
Vybrat jazyk, který nemá GC?

Jazyky GC používají kvůli jednoduchosti pro programátora, hlídat reference a uvolňovat paměť ručně je náchylné na chybu a memory leaky, zadarmo to ale není. Odstranit GC z javy je skoro jako odstranit javu, prostě to k tomu jazyku patří.

Jester

Re:Omezení alokace paměti
« Odpověď #4 kdy: 12. 03. 2018, 19:21:49 »
Vybrat jazyk, který nemá GC?

Jazyky GC používají kvůli jednoduchosti pro programátora, hlídat reference a uvolňovat paměť ručně je náchylné na chybu a memory leaky, zadarmo to ale není. Odstranit GC z javy je skoro jako odstranit javu, prostě to k tomu jazyku patří.
To je srandovní nepochopení otázky, které se ptá na haldu vs. zásobník. Go má GC a stejně když to jen trochu jde alokuje na zásobníku, jen když proměnná "escapuje", použije se halda a pak je za uvolnění zodpovědný GC. Právě proto jsou ekvivalentní programy v Go mnohem méně náročné na paměť než Java.


paskma

Re:Omezení alokace paměti
« Odpověď #5 kdy: 12. 03. 2018, 21:47:45 »
Ale zase alokace na haldě je v Javě mnohem rychlejší než v C++. Protože se jen posune pointer ve vyhrazené části paměti (object nursery). Takže je to vlastně skoro jako na zásobníku.

Samozřejmě GC to musí časem defragmentovat...

Je to design decision, když všechny alokace vypadají stejně, má to své výhody.

Dobře napsané C++ bude samozřejmě rychlejší než Java, ale zase produktivita programátora je v Javě mnohem mnohem vyšší.

Jester

Re:Omezení alokace paměti
« Odpověď #6 kdy: 12. 03. 2018, 22:04:11 »
Ale zase alokace na haldě je v Javě mnohem rychlejší než v C++. Protože se jen posune pointer ve vyhrazené části paměti (object nursery). Takže je to vlastně skoro jako na zásobníku.

Samozřejmě GC to musí časem defragmentovat...

Je to design decision, když všechny alokace vypadají stejně, má to své výhody.

Dobře napsané C++ bude samozřejmě rychlejší než Java, ale zase produktivita programátora je v Javě mnohem mnohem vyšší.
Jenže v tom Go jsou všechny alokace stejné, alokace je transparentní (něco jako return &MyObject{}). Ideální (nejefektivnější možný) postup je nechat udělat překladač escape analýzu a co fakt musí jít na haldu alokovat tcmallocem nebo něčím podobným, to je rychlé a nezpůsobuje to fragmentaci. Uvolnění buď počítáním referencí, to je brutálně rychlé, nebo trojbarevným GC pro nejnižší možnou latenci (v řádu mikrosekund, což je snesitelné pro většinu aplikací).

Re:Omezení alokace paměti
« Odpověď #7 kdy: 12. 03. 2018, 23:09:45 »
To je srandovní nepochopení otázky, které se ptá na haldu vs. zásobník. Go má GC a stejně když to jen trochu jde alokuje na zásobníku, jen když proměnná "escapuje", použije se halda a pak je za uvolnění zodpovědný GC. Právě proto jsou ekvivalentní programy v Go mnohem méně náročné na paměť než Java.

Máš pravdu, dotaz jsem správně nepochopil.

Go musí složitě kontrolovat, jestli alokace proměnné mu nepřeleze stack a případně dělat stack splitting. Pro stack je potřeba souvislá paměť, není možné ho fragmentovat, při větší potřebě paměti pro stack nemusí být aplikce schopná fungovat. Do heapy nacpu neomezené množství dat. Shrink stacku v Go je drahá věc a musí jí dělat GC napozadí. I heapa má svoje opodstatnění.

Jester

Re:Omezení alokace paměti
« Odpověď #8 kdy: 12. 03. 2018, 23:23:09 »
To je srandovní nepochopení otázky, které se ptá na haldu vs. zásobník. Go má GC a stejně když to jen trochu jde alokuje na zásobníku, jen když proměnná "escapuje", použije se halda a pak je za uvolnění zodpovědný GC. Právě proto jsou ekvivalentní programy v Go mnohem méně náročné na paměť než Java.

Máš pravdu, dotaz jsem správně nepochopil.

Go musí složitě kontrolovat, jestli alokace proměnné mu nepřeleze stack a případně dělat stack splitting. Pro stack je potřeba souvislá paměť, není možné ho fragmentovat, při větší potřebě paměti pro stack nemusí být aplikce schopná fungovat. Do heapy nacpu neomezené množství dat. Shrink stacku v Go je drahá věc a musí jí dělat GC napozadí. I heapa má svoje opodstatnění.
Stack splitting nemá nic společného se správou paměti, ten tam je kvůli goroutinám.