Paměťová a výpočetní náročnost JVM vs .NET

gamer

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #120 kdy: 20. 09. 2016, 16:11:29 »
Ten test má porovnávat použití pole struktur a pole referencí. Pole struktur, které vznikají v různém čase, je velmi netypické použití. A pole struktur, které nejsou v paměti za sebou, není pole struktur. Pokud chcete porovnávat kód, kde objekty vznikají v různém čase a nejsou v paměti za sebou, zařaďte do testu i to, že ty struktury musíte do toho pole nejprve zkopírovat. A když už budete v tom testování, doporučuju změřit i paměťovou náročnost.

Bohužel to pořád nechápete. V Javě NEJDE zaručit, že se alokátor bude chovat inkrementálně a objekty bude umísťovat za sebe. Defaultně se o to snaží, ale ne vždy to lze. Problém je to hlavně při fragmentaci haldy, pak si alokátor bude vytvářet objekty tam, kde je zrovna místo. Nelze to rozumně ovlivnit. Heap compaction nic moc neřeší, protože je to drahé.

Takže i když v Javě objekty vytvářím postupně, můžou být rozházené kdekoliv po fyzické paměti. V syntetickém testu se to neprojeví, protože na začátku je halda prázdná a všechno funguje hezky. Projeví se to až po delším běhu, kdy už je halda fragmentovaná.

Jsou lidé, kteří chtějí, aby ty objekty byly v paměti za sebou, protože vědí, že je budou sekvenčně procházet. Normálně se to řeší tak, že se vytvoří pole objektů (nikoliv pole referencí), což ale v Javě AFAIK nejde udělat.

Takže nemá žádný smysl porovnávat přístup přes pointer nebo přes index do pole, v tom není významý rozdíl. Problém nastane až s fragmentovanou pamětí, protože v Javě neovlivním, kde ten objekt bude v paměti fyzicky vytvořen.


gl

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #121 kdy: 20. 09. 2016, 16:11:51 »
Ten test je značně syntetický, normálně objekty vznikají v různém čase a nejsou v paměti za sebou.
Ten test má porovnávat použití pole struktur a pole referencí. Pole struktur, které vznikají v různém čase, je velmi netypické použití. A pole struktur, které nejsou v paměti za sebou, není pole struktur. Pokud chcete porovnávat kód, kde objekty vznikají v různém čase a nejsou v paměti za sebou, zařaďte do testu i to, že ty struktury musíte do toho pole nejprve zkopírovat. A když už budete v tom testování, doporučuju změřit i paměťovou náročnost.

points - pole struktur

ppoints - pole ukazatelů na struktury, které jsou v paměti za sebou

ppoints2 - pole ukazatelů na struktury, které nejsou v paměti za sebou.


paměťovou náročnost měřit nemusím. Ta je jasná.

Pokud změním pořadí alokování na

Kód: [Vybrat]
for(int i = 0; i < ARR_LEN; ++i){
    int index = (STEP_LEN * i) % ARR_LEN + (STEP_LEN * i)/ARR_LEN;
    ppoints2[index] = malloc(sizeof(struct Point));
  }

kde STEP_LEN dělí ARR_LEN, dostanu větší rozdíl v rychlosti.

gl

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #122 kdy: 20. 09. 2016, 16:35:12 »
zařaďte do testu i to, že ty struktury musíte do toho pole nejprve zkopírovat.

Nic kopírovat nemusím. Naopak inicializace je mnohem rychlejší. Tam je ještě větší rozdíl než v průchodu. Nemusím alokovat paměť pro každou položku zvlášť.


Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #123 kdy: 20. 09. 2016, 16:38:55 »
V Javě NEJDE zaručit, že se alokátor bude chovat inkrementálně a objekty bude umísťovat za sebe.
Když to bude pro výkon aplikace kritické, tak ta data (ne objekty) za sebe dám i v Javě. Klíčová je ta informace, že to v drtivé většině případů není důležité.

Jsou lidé, kteří chtějí, aby ty objekty byly v paměti za sebou, protože vědí, že je budou sekvenčně procházet.
Ano, tohle je problém. Že si někteří lidé myslí, že vědí, jak funguje procesor, a snaží se program neuměle předem optimalizovat. V lepším případě to dopadne tak, že na výkonu nic nepokazí a jenom znepřehlední kód. V horším případě kód zkomplikují i pro procesor, takže ten „optimalizovaný“ program bude pomalejší, než neoptimalizovaný. A pak je hrstka těch programátorů, kteří dokážou změřit, kdy je potřeba kód opravdu optimalizovat, a opravdu ho zoptimalizují (což opět prokážou měřením). Přičemž ten program může být napsaný v libovolném jazyce.

Normálně se to řeší tak, že se vytvoří pole objektů (nikoliv pole referencí), což ale v Javě AFAIK nejde udělat.
V Javě se to vyřeší například polem primitivních typů.

Problém nastane až s fragmentovanou pamětí, protože v Javě neovlivním, kde ten objekt bude v paměti fyzicky vytvořen.
Což je dobře, protože problém ve skutečnosti nastane už v okamžiku, kdy to někdo začne „optimalizovat“.

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #124 kdy: 20. 09. 2016, 16:41:25 »
Nic kopírovat nemusím. Naopak inicializace je mnohem rychlejší. Tam je ještě větší rozdíl než v průchodu. Nemusím alokovat paměť pro každou položku zvlášť.
Nevytrhávejte věty z kontextu. O kopírování jsem psal v případě, kdy ty struktury vznikají v aplikaci v různém čase.


gamer

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #125 kdy: 20. 09. 2016, 16:48:15 »
Když to bude pro výkon aplikace kritické, tak ta data (ne objekty) za sebe dám i v Javě. Klíčová je ta informace, že to v drtivé většině případů není důležité.
Jak to v Javě udělám? Drtivá většina je co? Drtivá většina aplikací Filipa Jirsáka?

Ano, tohle je problém. Že si někteří lidé myslí, že vědí, jak funguje procesor, a snaží se program neuměle předem optimalizovat.
Jste úplně vedle, s procesorem to vůbec nesouvisí. Jde o PAMĚŤ, protože pamět je násobně pomalejší než procesor. Jak funguje paměť je všeobecně známé, je mnohem rychlejší při sekvenčním čtení dat. Pokud mám velká data, vždy je výhodnější je mít v paměti za sebou. Není v tom žádná magie, je to úplně jednoduchý princip. Pokud nevíte, jak funguje pamět, tak raději zůstaňte u Javy, tam to ovlivnit nejde a budete spokojen.

V Javě se to vyřeší například polem primitivních typů.
Já ale nechci primitivní typy, chci normální objekty, proč bych to měl nějak hackovat?

Problém nastane až s fragmentovanou pamětí, protože v Javě neovlivním, kde ten objekt bude v paměti fyzicky vytvořen.
Což je dobře, protože problém ve skutečnosti nastane už v okamžiku, kdy to někdo začne „optimalizovat“.
Cože???

lol

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #126 kdy: 20. 09. 2016, 17:28:02 »
Citace
Cože???

To zřejmě mělo znamenat, že když programujete v jazyce, který si spravuje paměť sám, tak byste to měl akceptovat a přestat z toho dělat nějaké pseudocéčko. Jestli se přes to přenést nedokážete, tak prostě programujte v céčku. Simple as that.

gamer

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #127 kdy: 20. 09. 2016, 17:34:56 »
To zřejmě mělo znamenat, že když programujete v jazyce, který si spravuje paměť sám, tak byste to měl akceptovat a přestat z toho dělat nějaké pseudocéčko. Jestli se přes to přenést nedokážete, tak prostě programujte v céčku. Simple as that.

Nikdo z toho C dělat nechce, od začátku jde o to, že v Javě nejde udělat pole objektů. Nevidím žádný principielní problém, proč by se to s garbage collectorem udělat nedalo, prostě to tam není. Java evangelisti to hájí tak, že to vlastně není potřeba a nikdo to nechce a má se místo toho používat pole referencí.


gl

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #129 kdy: 20. 09. 2016, 18:02:06 »
Java evangelisti to hájí tak, že to vlastně není potřeba a nikdo to nechce a má se místo toho používat pole referencí.

Podle Java evangelistů není potřeba žádná featura, kterou Java neumí. Stejně v minulosti obhajovali neexistenci generik a lambda funkcí. Až vyjde Java 10, tak  změní názor a budou hodnotové typy cpát všude.

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #130 kdy: 20. 09. 2016, 18:03:48 »
Jak to v Javě udělám?
Především analyzuju, co ta příslušná část programu řeší, a budu se snažit najít nějaké jiné řešení. Nejčastěji to povede na jinou strukturu dat, možná jiný algoritmus. Pokud to náhodou bude ten výjimečný případ, kdy je potřeba mít data v paměti za sebou, uložím to třeba jako pole intů nebo bajtů.

Drtivá většina je co?
Drtivá většina je 99 % všech aplikací.

Jste úplně vedle, s procesorem to vůbec nesouvisí. Jde o PAMĚŤ, protože pamět je násobně pomalejší než procesor. Jak funguje paměť je všeobecně známé, je mnohem rychlejší při sekvenčním čtení dat. Pokud mám velká data, vždy je výhodnější je mít v paměti za sebou. Není v tom žádná magie, je to úplně jednoduchý princip. Pokud nevíte, jak funguje pamět, tak raději zůstaňte u Javy, tam to ovlivnit nejde a budete spokojen.
Nejvíce škod na výkonu aplikací napáchají programátoři, kteří pořád něco optimalizují, protože si myslí, že vědí, jak funguje paměť a procesor – myslí si, že přístup do paměti je O(1), pod přístupem do paměti si představují reálný režim i386 a to, že přístup do paměti mapuje runtime knihovna, operační systém i virtuální počítač zanedbávají, a optimalizují pro počítač s jedním procesorem a jedním vláknem, které provádí instrukce pěkně za sebou jak jsou ve spustitelném kódu.

Já ale nechci primitivní typy, chci normální objekty, proč bych to měl nějak hackovat?
Protože jste zjistil, že je to výkonově kritické místo vaší aplikace, a bez hackování to optimalizovat nejde. To je dost dobrý důvod pro hackování. Rozhodně mnohem lepší, než „tady to určitě bude pomalé, tak to nahackuju preventivně“.

Cože???
No jak je vidět i na této diskusi, do preventivních optimalizací se pouštějí především programátoři, kteří moc netuší, jak vypadá běh programu v moderním systému. Takže „optimalizují“ části programu, které to vůbec nepotřebují, „optimalizují“ tím, že hlavně znepřehlední kód, a občas ho pokazí tak, že už si s tím nic nezmůže ani kompilátor ani CPU, protože musí provádět ty nesmysly, které tam programátor při „optimalizaci“ napsal. Co se týče kvality výstupu, jsou na tom stejně, jako programátoři, kteří bez přemýšlení napíšou nějaký na první pohled nesmyslně zdlouhavý algoritmus, ale „optimalizátoři“ jsou proti nim nebezpečnější, protože si zpravidla nenechají vysvětlit, že dělají hlouposti.

gamer

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #131 kdy: 20. 09. 2016, 20:48:43 »
Už mě to moc nebaví, takže jenom krátce.

Vytvoření pole objektů není žádná optimalizace, je to přímočarý nativní přístup.

Vytvoření pole referencí na objekty je javovina, nic to nepřináší (kromě zjednodušení garbage collectoru), co se týká přístupu do paměti je to neoptimální. Většinou ta neoptimálnost nevadí, pokud ano, je to v Javě problém, protože to nejde normálně vyřešit, musí se to hackovat přes pole primitivních typů, což úplně rozbije datový model a kód v aplikaci.

Nazývat převedení pole referencí na pole objektů předčasnou optimalizací je úplně mimo, pole objektů by měl být nativní přístup, ale není, protože Java...

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #132 kdy: 20. 09. 2016, 21:14:36 »
Vytvoření pole referencí na objekty je javovina
A taky C++ovina, C#ovina, Pythonovina, JavaScriptovina, PHPovina atd. „Nativní“ je to možná tak v C.

nic to nepřináší (kromě zjednodušení garbage collectoru), co se týká přístupu do paměti je to neoptimální
Co se týče přístupu do paměti, je neoptimální pole objektů. Musíte předem vědět, jak je velké, jak velké jsou objekty, rezervovat místo na největší možný objekt, když s ním chcete něco dělat (filtrovat, řadit), musíte kopírovat celé objekty.

Nazývat převedení pole referencí na pole objektů předčasnou optimalizací je úplně mimo, pole objektů by měl být nativní přístup, ale není, protože Java...
Abych pravdu řekl, pořád vám nevěřím, že máte opravdu takovou hrůzu z referencí. Myslím si, že ve skutečnosti reference normálně používáte, akorát to nechcete přiznat, protože pak byste najednou musel vysvětlovat, proč jsou reference někdy dobré, ale jakmile jde o pole, jsou špatné. Protože jestli seznam 1000 osob, z nichž každá může mít jméno, prostřední jméno, příjmení a rodné příjmení, každé po 100 znacích, opravdu vytváříte tak, že alokujete 400 kB, jenom abyste se vyhnul referencím, a říkáte tomu optimální využití paměti…

v

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #133 kdy: 20. 09. 2016, 21:16:52 »
Vytvoření pole referencí na objekty je javovina
A taky C++ovina, C#ovina, Pythonovina, JavaScriptovina, PHPovina atd. „Nativní“ je to možná tak v C.

nic to nepřináší (kromě zjednodušení garbage collectoru), co se týká přístupu do paměti je to neoptimální
Co se týče přístupu do paměti, je neoptimální pole objektů. Musíte předem vědět, jak je velké, jak velké jsou objekty, rezervovat místo na největší možný objekt, když s ním chcete něco dělat (filtrovat, řadit), musíte kopírovat celé objekty.

Nazývat převedení pole referencí na pole objektů předčasnou optimalizací je úplně mimo, pole objektů by měl být nativní přístup, ale není, protože Java...
Abych pravdu řekl, pořád vám nevěřím, že máte opravdu takovou hrůzu z referencí. Myslím si, že ve skutečnosti reference normálně používáte, akorát to nechcete přiznat, protože pak byste najednou musel vysvětlovat, proč jsou reference někdy dobré, ale jakmile jde o pole, jsou špatné. Protože jestli seznam 1000 osob, z nichž každá může mít jméno, prostřední jméno, příjmení a rodné příjmení, každé po 100 znacích, opravdu vytváříte tak, že alokujete 400 kB, jenom abyste se vyhnul referencím, a říkáte tomu optimální využití paměti…
s váma je legrace :)

gl

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #134 kdy: 20. 09. 2016, 21:37:08 »
Vytvoření pole referencí na objekty je javovina
A taky C++ovina, C#ovina, Pythonovina, JavaScriptovina, PHPovina atd. „Nativní“ je to možná tak v C.

nic to nepřináší (kromě zjednodušení garbage collectoru), co se týká přístupu do paměti je to neoptimální
Co se týče přístupu do paměti, je neoptimální pole objektů. Musíte předem vědět, jak je velké, jak velké jsou objekty, rezervovat místo na největší možný objekt, když s ním chcete něco dělat (filtrovat, řadit), musíte kopírovat celé objekty.

Nazývat převedení pole referencí na pole objektů předčasnou optimalizací je úplně mimo, pole objektů by měl být nativní přístup, ale není, protože Java...
Abych pravdu řekl, pořád vám nevěřím, že máte opravdu takovou hrůzu z referencí. Myslím si, že ve skutečnosti reference normálně používáte, akorát to nechcete přiznat, protože pak byste najednou musel vysvětlovat, proč jsou reference někdy dobré, ale jakmile jde o pole, jsou špatné. Protože jestli seznam 1000 osob, z nichž každá může mít jméno, prostřední jméno, příjmení a rodné příjmení, každé po 100 znacích, opravdu vytváříte tak, že alokujete 400 kB, jenom abyste se vyhnul referencím, a říkáte tomu optimální využití paměti…

Tady nikdo hrůzu z referencí nemá. Ve většině případů je jejich použití asi optimální. Já programuji jen ve skriptovacích jazycích kde podobné optimalizace dělat nejdou a nikdy jsem je nepotřeboval. Reagoval jsem jen na tvrzení, že pole referencí je stejně efektivní jako pole pole hodnot.