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

dustin

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #45 kdy: 17. 09. 2016, 10:45:01 »
Ty vypocty sedi, ale otazka zni, proc je pouzit ArrayList? Docela bych rekl, ze je to dost umely priklad ne? Pole intu neni v mode? Btw i kdyby znela odpoved "ale ja potrebuju insert/delete/append", tak v ArrayListu se budou delat  ty same operace, co by se udelaly s arraycopy.

S kolekcemi (interně primárně arraylisty) se  pracuje velice pohodlně, rychle a hlavně bezpečně. Obzvláště použití streamů na běžné pořád opakované úkony kód zkracuje a zpřehledňuje. Pokud to interně v JVM pojede jako pole intu, jedině dobře.

Citace
Re: pole objektu je pole referenci, ma to i vyhody, obecne dela GC v Jave "dobre" kdyz jsou objekty male, naopak "humongous" objekty se s GC dost perou (jdou primo do old generation atd.).

Ano, ale pole hodnotových typů nebude přece o mnoho větší než původní pole referencí. A navíc tam nebudou ty malé objekty.


Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #46 kdy: 17. 09. 2016, 10:48:01 »
Ale pokud ten seznam dává smysl
Ano, to je to klíčové. Porovnávat programovací jazyky podle jedné miliardtiny způsobu jejich využití je nesmysl.

JSH

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #47 kdy: 17. 09. 2016, 10:52:13 »
Ale pokud ten seznam dává smysl
Ano, to je to klíčové. Porovnávat programovací jazyky podle jedné miliardtiny způsobu jejich využití je nesmysl.
A je opravdu pole malých věcí něco tak vzácného? Já mám pocit, že se s ním setkávám skoro furt.

Radek Miček

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #48 kdy: 17. 09. 2016, 11:01:10 »
Na masivní degradaci výkonu stačí i kolekce obsahující pouhé tisíce prvků. Přístup Javy totiž mrhá cachí a komplikuje práci prefetcheru.
Napsat špatný program lze v jakémkoli jazyce. Pokaždé přijdete s něčím novým, nicméně ještě jste nepřišel s ničím, co by dokazovalo vaše původní tvrzení, že absence uživatelských hodnotových typů v Javě způsobuje výrazně větší paměťové nároky Java aplikací.

Jak už jsem se opravil, měl jsem na mysli absenci uživatelsky def. hodnotových typů + specializace.

Příkladem je seznam čísel, když v Javě použijete generický ArrayList pro uložení 1000 intů. Předpokládejme, že aplikace běží nad HotSpotem a na 64 bitové architektuře. Pro takový seznam se alokuje minimálně 1002 objektů. Každý objekt obsahuje hlavičku (mark word 8 bajtů + klass pointer 8 bajtů; dohromady 16 bajtů). Instance ArrayList se bude skládat z hlavičky, pole, jenž obsahuje minimálně 1000 referencí, a nějakých dalších dat (minimálně 16 bajtů (hlavička) + 8 bajtů (reference na pole) + 8016 bajtů (pole referencí + hlavička) + velikost dalších dat). Pro každý int se vytvoří objekt, který AFAIK zabere min. 20 bajtů (nevím, zda JVM má nějakou minimální velikost objektů; pokud ano, může to být více). Tj. dohromady to zabere minimálně 8040 + 20 * 1000 = 28032 bajtů.

Analogická věc v .NET Core zabere zhruba 4032 bajtů + velikost dalších dat ve třídě List. Na rozdíl od Javy, kde se alokovalo 1002 objektů se zde alokují pouze 2 objekty (instance generické třídy List a pole).

Výše jsou uvedeny pouze odhady, které vycházejí z aktulních implementací - do budoucna se to může měnit.

Pole intu neni v mode? Btw i kdyby znela odpoved "ale ja potrebuju insert/delete/append", tak v ArrayListu se budou delat  ty same operace, co by se udelaly s arraycopy.

Jenže u pole se musím o zvětšování/zmenšování starat ručně, zatímco u ArrayListu to udělají automaticky metody, které volám.

Citace
Docela bych rekl, ze je to dost umely priklad ne?

Netroufnu si posoudit, jak je to ve webových aplikacích na sdílených hostinzích.

Osobně mi mnou popsané problémy přijdou celkem časté v kódu, který píši.

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #49 kdy: 17. 09. 2016, 11:01:22 »
Situací, kdy potřebujete pracovat s dvojicemi id a číslo je celá řada. Např. obyčejný e-shop chce nabízet produkty, které by se zákazníkovi mohly líbit - tj. pro každého zákazníka tam může mít seznam (id produktu, skóre) a z něj chce vždy vybrat např. 5 nejoblíbenějších produktů (s nejvyšším skóre), které zákazníkovi nebyly ukázány více než 4x (na to mj. potřebuje i mapu, id produktu -> kolikrát byl ukázán; pro níž byste v Javě opět nemohl použít standardní kolekci, pokud vám jde o alokaci paměti a výkon).
Obyčejný e-shop data o všech produktech, o všech objednávkách zákazníka a statistiky zákaznického chování drží v paměti webového serveru. Aha. Proto se nemůžeme domluvit, protože v mém světě má e-shop tahle data v SQL databázi, případně něco v NoSQL.

Takže to, že se dá prasit v každém jazyce a spousta lidí to dělá nějak vyplývá, že je to OK?
Ne, z toho vyplývá, že když to někdo naprasí v nějakém jazyce, není to nutně chyba toho jazyka.


Samozřejmě že to má vliv. Ale není to na první pohled vidět, protože ten vliv je rozprostřený po celém programu. Profiler neukáže, že to někde drhne, protože to drhne +- všude.
Jestli procesor stráví v idle 40 % nebo 50 % času je úplně jedno.

Pokud to nemá žádný vliv, tak proč se v současné době tolik řeší Data-Oriented-Design?
Protože se tolik neřeší. Řeší se pouze ve specifických případech.

Jinak původně se tazatel ptal na porovnání webhostingů pro Javu a .NET z hlediska využití zdrojů. Pořád se bavím tou představou, jak webhoster chce poskytnout hosting pro WAR aplikace, ale pak si uvědomí, že ty aplikace určitě budou neefektivně využívat CPU cache, tak radši zvolí .NET.

Obzvláště použití streamů na běžné pořád opakované úkony kód zkracuje a zpřehledňuje. Pokud to interně v JVM pojede jako pole intu, jedině dobře.
Myslíte rozhraní java.util.stream.IntStream?


Pavel Tisnovsky

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #50 kdy: 17. 09. 2016, 11:03:56 »
Ty vypocty sedi, ale otazka zni, proc je pouzit ArrayList? Docela bych rekl, ze je to dost umely priklad ne? Pole intu neni v mode? Btw i kdyby znela odpoved "ale ja potrebuju insert/delete/append", tak v ArrayListu se budou delat  ty same operace, co by se udelaly s arraycopy.

S kolekcemi (interně primárně arraylisty) se  pracuje velice pohodlně, rychle a hlavně bezpečně. Obzvláště použití streamů na běžné pořád opakované úkony kód zkracuje a zpřehledňuje. Pokud to interně v JVM pojede jako pole intu, jedině dobře.

Jasne o tom neni sporu, ale priznejme si - vetsina prikladu, co tady zaznela, nevede k pouziti ArrayListu, semanticky to byly vetsinou mnoziny (Set). Coz samozrejme nic nemeni na tom, ze i Set<int> a ne Set<Integer> by bylo fajn mit primo v zakladni knihovne. No nestalo se.

Citace
Citace
Re: pole objektu je pole referenci, ma to i vyhody, obecne dela GC v Jave "dobre" kdyz jsou objekty male, naopak "humongous" objekty se s GC dost perou (jdou primo do old generation atd.).

Ano, ale pole hodnotových typů nebude přece o mnoho větší než původní pole referencí. A navíc tam nebudou ty malé objekty.

To byla spis odpoved na tu cast diskuze, kde se resila pole objektu, coz v cecku odpovida poli struktur. Priklad:


struct x
{
    int id;
    float perc;
};

int main()
{
    struct x zaznam;
    struct x pol
e[1000];
    printf("%ld\n", sizeof(zaznam));
    printf("%ld\n", sizeof(pole));
    return 0;
}


Vypise na vystup 8 bajtu pro "zaznam" a 8000 bajtu pro pole.

V Jave to takto nejde, ma to svoje duvody:

1) historie
2) zajimave je, ze v Jave se nikdy nemusi resit velikosti objekty, protoze ty jsou bud konstantni nebo jde o pole, takze pole objektu je pohodicka - pole referenci. Ze ma nejaky objekt v sobe String? Neni problem, to je stejne reference na objekt s vnitrnim polem jako atributem. atd. Neni to asi vsude idealni, ale ta jednoduchost pro JVM z toho asi vyplyva.

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #51 kdy: 17. 09. 2016, 11:05:59 »
A je opravdu pole malých věcí něco tak vzácného? Já mám pocit, že se s ním setkávám skoro furt.
Jenže tady řešíme něco mnohem vzácnějšího – častou iteraci přes pole malých struktur (tj. ne primitivních typů), která ovšem programátorovi nestojí za optimalizaci.

gl

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #52 kdy: 17. 09. 2016, 12:44:04 »
Jasně. Takže libovolná implementace radix tree, spojového seznamu nebo HTML parseru bude efektivně využívat cache procesoru, pokud bude napsaná v C++.

Spojové struktury jako seznamy a stromy se právě z důvodu využití cache dnes moc nepoužívají. Přečti si něco o cache obvious algoritmech.

gl

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #53 kdy: 17. 09. 2016, 12:53:43 »
A je opravdu pole malých věcí něco tak vzácného? Já mám pocit, že se s ním setkávám skoro furt.
Jenže tady řešíme něco mnohem vzácnějšího – častou iteraci přes pole malých struktur (tj. ne primitivních typů), která ovšem programátorovi nestojí za optimalizaci.

Jakou optimalizaci? V jiných jazycích je to triviální. Volbu správné datové struktury bych optimalizací nenazýval.

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #54 kdy: 17. 09. 2016, 13:21:14 »
Jasně. Takže libovolná implementace radix tree, spojového seznamu nebo HTML parseru bude efektivně využívat cache procesoru, pokud bude napsaná v C++.

Spojové struktury jako seznamy a stromy se právě z důvodu využití cache dnes moc nepoužívají. Přečti si něco o cache obvious algoritmech.
To je ale v rozporu s tím, co psal JSH, že ke správnému využití cache stačí použít správný programovací jazyk. Přečíst by si to tedy měl JSH.

Jakou optimalizaci? V jiných jazycích je to triviální.
Asi byste si měl přečíst něco o cache obvious algoritmech. Dozvěděl byste se třeba, že se spojové seznamy a stromy nepoužívají, a to bez ohledu na programovací jazyk – protože ten to nijak magicky nezachrání.

Volbu správné datové struktury bych optimalizací nenazýval.
Tak to byste si měl něco přečíst i o datových strukturách. Protože jedna datová struktura může být vhodná z hlediska paměťové náročnosti, obvykle jiná bývá vhodná z hlediska rychlosti (a to je ještě různé pro čtení a pro zápis), jiná datová struktura může být vhodná z hlediska snadnosti použití nebo složitosti implementace. Která z nich je ta správná? Obvykle ta, co se nejsnáz používá, ale někdy je potřeba optimalizovat – a pak je často nutné změnit datovou strukturu.

Radek Miček

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #55 kdy: 17. 09. 2016, 13:37:01 »
Situací, kdy potřebujete pracovat s dvojicemi id a číslo je celá řada. Např. obyčejný e-shop chce nabízet produkty, které by se zákazníkovi mohly líbit - tj. pro každého zákazníka tam může mít seznam (id produktu, skóre) a z něj chce vždy vybrat např. 5 nejoblíbenějších produktů (s nejvyšším skóre), které zákazníkovi nebyly ukázány více než 4x (na to mj. potřebuje i mapu, id produktu -> kolikrát byl ukázán; pro níž byste v Javě opět nemohl použít standardní kolekci, pokud vám jde o alokaci paměti a výkon).
Obyčejný e-shop data o všech produktech, o všech objednávkách zákazníka a statistiky zákaznického chování drží v paměti webového serveru.

Nic takového jsem nenapsal: Např. slovo objednávka jsem nezmínil ani jednou. A rozhodně jsem neříkal, kde se ta data drží. Mluvil jsem o vektoru dvojic (id produktu, skóre), který si načtete třeba z databáze nebo si ho spočítáte, pokud již nebyl spočten a uložen v cachi.

JSH

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #56 kdy: 17. 09. 2016, 13:42:36 »
To je ale v rozporu s tím, co psal JSH, že ke správnému využití cache stačí použít správný programovací jazyk. Přečíst by si to tedy měl JSH.
Kde jsem něco takového psal?

Radek Miček

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #57 kdy: 17. 09. 2016, 13:45:08 »
A je opravdu pole malých věcí něco tak vzácného? Já mám pocit, že se s ním setkávám skoro furt.
Jenže tady řešíme něco mnohem vzácnějšího – častou iteraci přes pole malých struktur (tj. ne primitivních typů), která ovšem programátorovi nestojí za optimalizaci.

Nejenom - řešíme tu i to, že takové pole nebo seznam zabere v Javě více paměti (a to i několikanásobně) než v C#, kde jsou ty struktury deklarovány jako struct.

Re:Pametova a vypocetni narocnost JVM vs .NET
« Odpověď #58 kdy: 17. 09. 2016, 13:48:04 »
Nic takového jsem nenapsal: Např. slovo objednávka jsem nezmínil ani jednou. A rozhodně jsem neříkal, kde se ta data drží. Mluvil jsem o vektoru dvojic (id produktu, skóre), který si načtete třeba z databáze nebo si ho spočítáte, pokud již nebyl spočten a uložen v cachi.
Normální program si z databáze nenačte pět dvojic (id produktu, skóre), ale načte si pět záznamů (název produktu, odkaz na produkt, odkaz na obrázek produktu, skóre). Optimalizovat uložení těch pěti záznamů v paměti aplikace tak, aby se vešly do cache procesoru, je nesmysl na entou. Ale pokud si někdo chce hrát se strukturami proměnlivé délky (minimálně ten název produktu bude text s různou délkou), ať si to užije. Drobným problémem bude, že dotyčný autor sice bude mít optimalizovaný výpis (ne získání) 5 doporučených produktů, akorát mu k tomu bude chybět ten e-shop (který by za tu dobu napsal ten, kdo neřeší nesmyslné optimalizace).

Re:Paměťová a výpočetní náročnost JVM vs .NET
« Odpověď #59 kdy: 17. 09. 2016, 13:50:01 »
To je ale v rozporu s tím, co psal JSH, že ke správnému využití cache stačí použít správný programovací jazyk. Přečíst by si to tedy měl JSH.
Kde jsem něco takového psal?

Pro efektivní využití cache bohatě stačí aby jazyk zbytečně nevkládal zbytečné skákání po pointerech.