Java Lambdas jsou několikanásobně pomalejší

Zelenac

Java Lambdas jsou několikanásobně pomalejší
« kdy: 19. 03. 2016, 13:00:43 »
Jak uz zde nekteri mi priznivci vedi, mam rad eventy a Javu, a tak jsem si zkousel zmerit rychlost standardnich konstrukci s temi lamdovskymi a ve vsech pripadech mi vyslo, ze lambdy jsou pomalejsi, v nekterych pripadech az nekolikanasobne. A ja blahovy jsem si myslel, ze lambdy v pozadi konecne funguji jako primy vstup do metody/funkce, a ono zrejme ne. Dela se z nich az moc velke terno ale je to fakt slabota. Zejo?
« Poslední změna: 21. 03. 2016, 09:23:23 od Petr Krčmář »


Zelenac

Re:Java Lamdas slow as fak
« Odpověď #1 kdy: 19. 03. 2016, 13:14:01 »
Kód: [Vybrat]
package main;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BinaryOperator;

class Parameters {
public final int p1;
public final int p2;
public Parameters(int p1, int p2) {
this.p1 = p1;
this.p2 = p2;
}
}

class Main {

static final long SIZE = 50000000;

static long tsuma = 0;

public static void sum(long val) {
tsuma += val;
}

public static int vypocet(Parameters params) {
return params.p1 * params.p2;
}


public static void main(String[] args) {
List<Long> list = new ArrayList<>();
for(long i = 0; i < SIZE/3; i++ ) {
list.add(i);
}

long timer;
long supp;

/**
* Obycejny se statickou metodou
*/
timer = System.nanoTime();
for(int i = 0; i < list.size(); i++)
sum(list.get(i));
timer = System.nanoTime() - timer;
System.out.println(timer + " " + tsuma);

/*
* Lambda se statickou metodou
*/
tsuma = 0;
timer = System.nanoTime();
list.forEach( (value) -> sum(value) );
timer = System.nanoTime() - timer;
System.out.println(timer +" " + tsuma);

/**
* Lambda se streamem
*/
supp = 0;
timer = System.nanoTime();
supp = list.stream().mapToLong(value -> value).reduce(1, (a, b) -> a += b );
timer = System.nanoTime() - timer;
System.out.println(timer + " " + supp);


/**
* Volani pres new bez lambdy
*/
supp = 0;
timer = System.nanoTime();
for(int i = 0; i < SIZE; i++) {
supp += vypocet(new Parameters(i, i));
}
timer = System.nanoTime() - timer;
System.out.println(timer + " " + supp);


/**
* Lambda
*/
BinaryOperator<Integer> op = (a, b) -> { return a * b; };
supp = 0;
timer = System.nanoTime();
for(int i = 0; i < SIZE; i++) {
supp += op.apply(i, i);
}
timer = System.nanoTime() - timer;
System.out.println(timer + " " + supp);
}
}



výstup:

Kód: [Vybrat]
35440642 ns   
77238271 ns
40472188 ns   
37840783 ns     
1874345240 ns  //zatracene pomala lambda


Re:Java Lamdas slow as fak
« Odpověď #2 kdy: 19. 03. 2016, 13:20:57 »
- takhle se mikrobenchmarky nikdy nemohou psat
- pokud te prekvapuje, ze netere kusy tohohle kodu budou pomalejsi, nez jine, tak se zamysli nad tim, jak se to preklada. (aha "A ja blahovy jsem si myslel, ze lambdy v pozadi konecne funguji jako primy vstup do metody/funkce" rika vsechno)

Zelenac

Re:Java Lamdas slow as fak
« Odpověď #3 kdy: 19. 03. 2016, 13:27:19 »
Dle speciální matematicko-redukční metody vyplynulo, že s benchmarky napsanými takhle pod sebeou se vejdu do tolerance +-0.3569991%  relativně k benchmarkům spouštěným zvlášť. [1]

[1] Jan Amos Komínský, Highest Computer Scientist Methodology in Java, 2016, CERN

Re:Java Lamdas slow as fak
« Odpověď #4 kdy: 19. 03. 2016, 14:26:20 »
Dle speciální matematicko-redukční metody vyplynulo, že s benchmarky napsanými takhle pod sebeou se vejdu do tolerance +-0.3569991%  relativně k benchmarkům spouštěným zvlášť. [1]

[1] Jan Amos Komínský, Highest Computer Scientist Methodology in Java, 2016, CERN

Tak sis zatroloval a s tim bychom to mohli asi uzavrit...


zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Java Lamdas slow as fak
« Odpověď #5 kdy: 19. 03. 2016, 14:30:03 »
Jak uz zde nekteri mi priznivci vedi, mam rad eventy a Javu, a tak jsem si zkousel zmerit rychlost standardnich konstrukci s temi lamdovskymi a ve vsech pripadech mi vyslo, ze lambdy jsou pomalejsi, v nekterych pripadech az nekolikanasobne. A ja blahovy jsem si myslel, ze lambdy v pozadi konecne funguji jako primy vstup do metody/funkce, a ono zrejme ne. Dela se z nich az moc velke terno ale je to fakt slabota. Zejo?

Změň jazyk ;)

javaman

Re:Java Lamdas slow as fak
« Odpověď #6 kdy: 19. 03. 2016, 14:34:42 »
Jak uz zde nekteri mi priznivci vedi, mam rad eventy a Javu, a tak jsem si zkousel zmerit rychlost standardnich konstrukci s temi lamdovskymi a ve vsech pripadech mi vyslo, ze lambdy jsou pomalejsi, v nekterych pripadech az nekolikanasobne. A ja blahovy jsem si myslel, ze lambdy v pozadi konecne funguji jako primy vstup do metody/funkce, a ono zrejme ne. Dela se z nich az moc velke terno ale je to fakt slabota. Zejo?

Změň jazyk ;)

Tak určitě, ať zahodí ten nejlepší a jde do nějakého horšího. Takhle se to nedělá. Nejdříve se naučím jeden dobře a až pak se dívám jinam. Hlavně měl štěstí, protože si vybral zrovna to nejlepší. Jen tomu musí věnovat pár let, aby se dostal na trochu lepší úroveň.

M

Re:Java Lamdas slow as fak
« Odpověď #7 kdy: 19. 03. 2016, 14:38:31 »
Zacni pouzivat C#, jediny jazyk, ktery ma vsechno smysluplne.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Java Lamdas slow as fak
« Odpověď #8 kdy: 19. 03. 2016, 14:43:42 »
Jak uz zde nekteri mi priznivci vedi, mam rad eventy a Javu, a tak jsem si zkousel zmerit rychlost standardnich konstrukci s temi lamdovskymi a ve vsech pripadech mi vyslo, ze lambdy jsou pomalejsi, v nekterych pripadech az nekolikanasobne. A ja blahovy jsem si myslel, ze lambdy v pozadi konecne funguji jako primy vstup do metody/funkce, a ono zrejme ne. Dela se z nich az moc velke terno ale je to fakt slabota. Zejo?

Změň jazyk ;)

Tak určitě, ať zahodí ten nejlepší a jde do nějakého horšího. Takhle se to nedělá. Nejdříve se naučím jeden dobře a až pak se dívám jinam. Hlavně měl štěstí, protože si vybral zrovna to nejlepší. Jen tomu musí věnovat pár let, aby se dostal na trochu lepší úroveň.
Nikdo neříkal, ať zahodí nejlepší. Řeč byla o Javě ;)

javaman

Re:Java Lamdas slow as fak
« Odpověď #9 kdy: 19. 03. 2016, 14:45:12 »
To právě nechápu. Stačí ji umět a nic lepšího nenajdeš. Proto je Java taky všude, že jo.

Re:Java Lamdas slow as fak
« Odpověď #10 kdy: 19. 03. 2016, 15:40:59 »
To právě nechápu. Stačí ji umět a nic lepšího nenajdeš. Proto je Java taky všude, že jo.

No to bych nerekl. Java je vsude, protoze je to slusne navrzeny mainstream, co mel stesti. Ale ze by to bylo "nic lepsiho nenajdes", tak to urcite ne. Uz jenom, pokud zustaneme na JVM, je pro nektere veci (unittesty se Spockem jsou pekny priklad) lepsi Groovy, Kotlin zakulatil syntaxi, nektere veci lepe napises ve Scale...

Re:Java Lamdas slow as fak
« Odpověď #11 kdy: 19. 03. 2016, 15:50:24 »
Je tam nekolik problemu:

JIT optimalizuje az po nekolika (tisicich) pusteni dane funkcr. Proto je vhodne zvolit nejaky microbenchmark tool  - JHM treba a korektne napsat benchmarky.

Zalezi jak se napise kod. Vytvaret lambdu pro kazdy prvek, kdyz se vlasyne nemeni, je zcela zbytecne, navic by se o to mozna prave postaral JIT. I tak normalne by to nevadilo, ale v takovem umelem benchmatk se to pochopitelne projevi.

Posledni priklad - letmo - vytvari pro kazde volani 3x Integer class. Zatimco u for verze kompolator nejspis zcela vyhodi ten temporary objekt ci ho da na stack, takze vysledkem bude zcela primy preklad pres par scitani.

Je treba rict, ze lambda je ve sve podstate virtualni callback, ktery negativne ovlivnuje moznosti optimalizace. Bezne to nevadi, bo moderni SW je na tom postaveny, ale v pripade jednoduchych matematickych smycek typu secti mi pole cisel to neni nejlepsi varianta.

Ale jeste jednou viz vyse - dost mozna cast vyresi JIT po vice pruchodech.

Re:Java Lamdas slow as fak
« Odpověď #12 kdy: 19. 03. 2016, 16:14:05 »
nezdrzuje to nahodou ten autoboxing/unboxing?

Pavel Tisnovsky

Re:Java Lamdas slow as fak
« Odpověď #13 kdy: 19. 03. 2016, 19:27:16 »
Zkus si ten kod vyhodit do dalsi metody a tu spoustet n-krat (kde n bude dostatecne velke cislo), pak si udelej tabulku s casy, jestli (a ktere) se zlepsi atd. Protoze JIT tady funguje mozna trosku jinak nez ocekavas.

Taky je zajimavy se mrknout na vygenerovany bajtkod, ono tam bude (jak pise ziktofel) dost operaci s auto(un)boxingem. To sice JIT taky pochopi a odstrani, ale musi se napred spustit, aby dostal sanci :)

Zelenac

Re:Java Lamdas slow as fak
« Odpověď #14 kdy: 19. 03. 2016, 21:10:03 »
Takže ne lambda, ale java jitr slow as fak. No a co lambdy a JavaFX eventy, tam mi to vylozene prijde ze eventy ve swingu jsou praktičtější, proste dam addListener(new Handler(){..} ) a prepisu si eventy na ktere chci reagovat v jedinem  addListenerovi, navic je to i prenositelnejs na starsi jdk.