IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Rychlostní test Java vs Scala

Aktivity
Avatar
Milan Gallas
Tvůrce
Avatar
Milan Gallas:5.3.2017 17:41

Ahoj, mám otázku ohledně porovnání rychlosti těchto 2 jazyků. Měl jsem za to, že funkcionální scala bude v rychlostních testech mnohonásobně rychlejší, než java. Po testech jsem nechápavě koukal na výsledky.

Scala je až 30 pomalejší. Níže přikládám testovací kódy. Bych bych rád, za každou poznámku, jestli je můj kód v scale neefektivní, nebo je ten jazyk tak nezkutečně pomalý. Dále bych poprosil jestli někdo podobně testoval, tak aby se podělil o jeho výsledky a zkušenosti.
Předem díky.

Java - http://www.itnetwork.cz/dev-lighter/896
scala - http://www.itnetwork.cz/dev-lighter/897

 
Odpovědět
5.3.2017 17:41
Avatar
Neaktivní uživatel:5.3.2017 17:57

Funkcionalni neznamena rychlejsi. Viz rychlost kodu napsaneho v C/C++.

Nahoru Odpovědět
5.3.2017 17:57
Neaktivní uživatelský účet
Avatar
Odpovídá na Milan Gallas
Marian Benčat:5.3.2017 19:01

Téměř každý test jde napsat tak, aby něco bylo mnohonásobně pomalejší, než něco jiného.. Jen u PHP je to problém, to se něco jiného musí napsat extrémně špatně, aby PHP bylo rychlejší.

K tvému testu.. Použij v Javě STD knihovnu na to pole a uvidíš, jak to bude najednou 30x pomalejší v Javě, kvůli boxingu primitivních typů ;-)

To,, že je nějaký JAZYK pomalejší, není způsobeno tím, že má nějakou "instrukci" navíc, ale o tom, jak efektivně zachází s pamětí.. A i já jsem schopný napsat kód v C#, který spustím 3x, úplně ten samý kód nad úplně těmi samými daty a jednou potrvá 1sec, podruhé 20 a potřetí klidně zase 8sec.

Nahoru Odpovědět
5.3.2017 19:01
Totalitní admini..
Avatar
Milan Gallas
Tvůrce
Avatar
Odpovídá na Marian Benčat
Milan Gallas:5.3.2017 22:43

Ahoj Mariane, právě proto jsem zveřejnil kódy, které testuji. Pokud dokážeš zrychlit kód napsaný ve scale, tak aby se přiblížil rychlosti javy, tak ho prosím zveřejni.

K tvému komentáři, proč bych používal v javě, něco co je mnohonásobné pomalejší při tomto testu? testuji konstrukce jazyka, což je naprostý základ, nikoliv nějaké knihovny.

 
Nahoru Odpovědět
5.3.2017 22:43
Avatar
Odpovídá na Milan Gallas
Marian Benčat:5.3.2017 22:48

Todle nemá nic společného s knihovnou, to je jen způsob, jak ukázat jednu z extrémních nevýhod javy, která má negativní dopad na její výkon a sice type erasure v generice a tudíž boxing primitivních typů.

Nevím jak zrychlit kód ve Scale, popravdě mě jazyky na bázi JVM nezajímají. Považuji to za mrtvou platformu, to je ale muj nazor a je mi jasné, že ty a David máte názor odlišný.

Nahoru Odpovědět
5.3.2017 22:48
Totalitní admini..
Avatar
coells
Tvůrce
Avatar
Odpovídá na Milan Gallas
coells:6.3.2017 0:08

Psát benchmark je umění a kvůli několika chybám (které vůbec nejsou zjevné) testuješ něco trochu jiného.

Ty tvé dva kódy mi běžely daleko rychleji než tobě, scala asi 1.5x pomalejší než java, určitě ne 20x.
Nejspíš mám jinou verzi knihoven, ale to je celkem jedno.

Zkus si pohrát s indexováním matice: matrix[i][j] = i*j => matrix[j][i] = i*j, schválně jak moc java zpomalí.
Stejně prohoď indexy i ve scale, co se stane, měl bys dostat hodně odlišná čísla od původního testu.
To je první chyba, kdy místo rychlosti runtime omylem testuješ L2 cache.

Pro lepší test přestaň pracovat s velkými úseky paměti, pokud si nejsi jistý, jak to funguje uvnitř.
Napiš si metodu, která bude opakovaně provádět operace nad menším polem, např. 1kB.
Metoda by měla trvat řádově alespoň desítky milisekund, abys zase neměřil něco jiného.

Tuhle metodu několikrát zavolej bez měření času, aby JIT dostal šanci a pak začni měřit, kolikrát stihneš metodu provést během časového úseku, řekněme 10 sekund.
Stejný postup udělej ve scale a závěrečné porovnání nepočítej na čase, ale na počtu volání.

Funkcionální jazyky jsou obecně pomalejší než procedurální, to je trade-off za vyšší abstrakci kódu.
Existují triky, jak se s tím vyrovnat, ale tvůj test je nefér k javě, protože ve scale jsi napsal imperativní kód, ne funkcionální.
Zkus si napsat ještě třetí test, kdy napíšeš funkcionální program tak, jak má vypadat.
Tady je to zjevně outer-product V * V', kde V je range.
Schválně, o kolik bude scala pomalejší, když v ní napíšeš čistý kus kódu?

Editováno 6.3.2017 0:10
 
Nahoru Odpovědět
6.3.2017 0:08
Avatar
shaman
Člen
Avatar
Odpovídá na Milan Gallas
shaman:6.3.2017 9:51

Tiez nie som expert v Scale ale

  • var sa nepouziva. Pouzivaj iba immutable types ako je val.
  • for loop sa v Scale pise viac funckne, nejak takto
val result =
(1 to 10000).foreach { i1 =>
      (1 to 10000).foreach { i2 =>
        i1 * i2
      }
    }
Nahoru Odpovědět
6.3.2017 9:51
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Milan Gallas
Tvůrce
Avatar
Odpovídá na coells
Milan Gallas:6.3.2017 19:27

Dobře další test je od toho prvního odlišný. Nic neukládám do proměnných, což jsem původně v javě dělal a kód se zrychlil a ani nic nevypisuji na obrazovku. Prostě dám cyklus od 1 do 200 a dané číslo pošlu do funkce, která mi vypočítá faktoriál. Nic víc, ani méně.

Scala je zase neuvěřitelně pomalá. Ty výsledky jsou ale příliš rozdílné proto ještě mrknu na verze.

java - http://www.itnetwork.cz/dev-lighter/902
scala - http://www.itnetwork.cz/dev-lighter/903

Je tohle jeden z testů, o kterém jsi mluvil.

V javě to zdržuje ta nešikovná implementace Bigintiger, ale i tak je to o dost rychlejší.

Editováno 6.3.2017 19:28
 
Nahoru Odpovědět
6.3.2017 19:27
Avatar
coells
Tvůrce
Avatar
Odpovídá na Milan Gallas
coells:6.3.2017 20:40

BigInteger má špatnou implementaci, takže jen měříš, jak je interně pomalý.
Navíc v Javě pracuješ s integerem, takže alokuješ méně objektů než ve Scale.

Když jsem to upravil, byla Java rychlejší opět asi o polovinu.
Napsat dobrý benchmark je prostě hodně těžké, ať napíšeš cokoliv, tak se na výsledky moc nekoukej, nic ti neřeknou.

Scala je pomalejší než Java a obecně bude ještě pomalejší, protože psát rychlý kód vyžaduje hodně zkušeností a znalostí.
V Clojure také používáme řadu nenápadných triků, které dělají obrovský rozdíl.

 
Nahoru Odpovědět
6.3.2017 20:40
Avatar
shaman
Člen
Avatar
Odpovídá na Milan Gallas
shaman:6.3.2017 22:55

Prave pozeram ine benchmarky a tiez im vacsinou vychadza java ako rychlejsia: https://benchmarksgame.alioth.debian.org/u64q/scala.html

Myslim ze pravdu ma aj @coells ze na vyuzitie scaly treba skusenosti a znalosti. Taktiez Scala je este mlady jazyk v porovnani s Javou.

Nahoru Odpovědět
6.3.2017 22:55
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Odpovídá na shaman
Patrik Valkovič:6.3.2017 23:04

Scala bude vždy pomalejší, už jen z principu funkcionálního jazyka. Nemám se Scalou zkušenosti, ale pokud vím, tak funkcionální jazyky jsou Immutables - to přidává nějakou režii a v porovnání s Javou, která tuto režii nemá, to jde samozřejmě znát.
Taky předpokládám, že kompilátor Javy má větší volnost, tedy může mnohem lépe optimalizovat, na rozdíl od funkcionálních jazyků, kde pro optimalizaci takový prostor není.

Nahoru Odpovědět
6.3.2017 23:04
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Odpovídá na Patrik Valkovič
Neaktivní uživatel:6.3.2017 23:51

Dovolim si oponovat s immutabilitou. Uz jen z povahy toho co rikas: pokud budu kompilovat tak immutabilitu kontroluju pri kompilaci a pak? Kde je ta rezie?

Problem je spis v tom, ze kdyz pises plne funkcionalne mas vetsi naroky na pamet, jak uz tu zaznelo.

Nahoru Odpovědět
6.3.2017 23:51
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Patrik Valkovič:7.3.2017 9:12

Ta režie je až během běhu. Když odstraníš nějaký prvek ve spojáku, tak se během běhu musí všechny jeho předci překopírovat. To stejné platí i například pro stromy. To je režie, kterou Java nemá, dokud si ji explicitně nenapíšeš, protože hodnoty předává referencí.
Z immutables potom plyne další důsledek - funkcionální jazyky nemají klasické pole, protože při každé změně by se muselo celé pole zkopírovat. Takže místo pole používá právě spoják - další degradace výkonu, protože pro přístup k prvku je namísto konstantní složitosti použita složitost lineární. To jsou hold všechno věci, které vychází z logiky jazyka, kompilace s tím nemá co dělat.
No a v neposlední řadě paměť paměť paměť....když se všechno kopíruje, někam se to musí házet. Když jsou provolávány stovky funkcí, někam se tyto udaje musí uložit.

Nahoru Odpovědět
7.3.2017 9:12
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Odpovídá na Patrik Valkovič
Neaktivní uživatel:7.3.2017 9:26

Beres Rust jako funkcionalni jazyk?

Nahoru Odpovědět
7.3.2017 9:26
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Patrik Valkovič:7.3.2017 9:34

Nevím, s Rustem jsem nedělal, mluvím ze zkušeností s Clojurem a Lispem.

Nahoru Odpovědět
7.3.2017 9:34
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Odpovídá na Patrik Valkovič
Neaktivní uživatel:7.3.2017 9:45

To by vysvetlovalo nasi odlisnou zkusenost. OK.

Editováno 7.3.2017 9:45
Nahoru Odpovědět
7.3.2017 9:45
Neaktivní uživatelský účet
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 16 zpráv z 16.