Große Ausführungszeit Unterschied zwischen java Lambda-vs Anonyme Klasse

War ich neugierig auf die Leistung der Schaffung von java8 lambda-Instanzen, gegen die gleiche anonyme Klasse. (Messung erfolgt auf win32-java build 1.8.0-ea-b106). Ich habe sehr einfaches Beispiel, und gemessen wenn java vorschlagen, einige Optimierung von new Bediener beim erstellen lambda-Ausdruck:

static final int MEASURES = 1000000;
static interface ICallback{
    void payload(int[] a);
}
/**
* force creation of anonymous class many times
*/
static void measureAnonymousClass(){
    final int arr[] = {0};
    for(int i = 0; i < MEASURES; ++i){
        ICallback clb = new ICallback() {
            @Override
            public void payload(int[] a) {
                a[0]++;
            }
        };
        clb.payload(arr);
    }
}
/**
* force creation of lambda many times 
*/
static void measureLambda(){ 
    final int arr[] = {0};
    for(int i = 0; i < MEASURES; ++i){
        ICallback clb = (a2) -> {
            a2[0]++;
        };
        clb.payload(arr);
    }
}

(Vollständigen code können dort getroffen werden: http://codepad.org/Iw0mkXhD) Das Ergebnis ist eher vorhersehbar - lambda gewinnt 2 mal.

Aber wirklich wenig zu verschieben, um Verschluss zeigt sehr schlechte Zeit für die lambda. Anonyme Klasse gewinnt 10 mal!!!
So, jetzt anonyme Klasse sieht wie folgt aus:

ICallback clb = new ICallback() {
        @Override
        public void payload() {
            arr[0]++;
        }
    };

Lambda funktioniert wie folgt:

ICallback clb = () -> {
            arr[0]++;
        };

(Vollständigen code können dort getroffen werden: http://codepad.org/XYd9Umty )
Kann jemand mir erklären, warum existiert so groß (schlecht) Unterschied im Umgang mit der Schließung?

  • Das ist ein sehr naiver Ansatz zu microbenchmarking. Zumindest verwenden System.nanoTime und die Einführung der " Wegwerf-Ausführungen zum Aufwärmen der JVM. Mehrere System.gc() Anrufe zwischen den Ausführungen wäre auch eine gute Idee. Idealerweise tun Sie dies mit Google Bremssattel oder Oracle-jmh.
  • eigentlich habe ich vorgesehen, dieser Hinweis, dass ist der Grund, warum ich 2 Messungen durchgeführt, wenn measureLambda zuerst ausgeführt, und wenn measureLambda läuft nach measureAnonymousClass - ohne Auswirkungen auf alle! Und nanoTime zeigen können, Unterschied in der genauen Messung, aber nicht wenn ich Rede 10 mal
  • Meinst du 10 Sekunden? Auch, es hätte geholfen, wenn Sie enthalten den Hinweis zum ausführen von sowohl Auftragseingang als im text Ihrer Frage.
  • oh Nein, für meine CPU: für den ersten Fall (wo die lambda gewinnt) 7ms vs 14ms, für den zweiten Fall (mit Verschluss wo die lambda verlieren) 160ms vs 20ms. Die änderung der Bestellung hat keinen Einfluss auf gemessene Zeit.
  • Die Genauigkeit der currentTimeMillis ist oft auf dem Niveau von einem Zehntel einer Sekunde (Plattform-abhängig). Die Genauigkeit der nanoTime ist in der Regel auf der Ebene einer Mikrosekunde. Auch, nur die Neuordnung Ausführungen beweist gar nichts: jeder code-Pfad muss erwärmt werden, bis auf seine eigenen. Warm-up-Ausführungen ist der Weg, es zu tun und garbage collection muss überwacht werden, für.
  • Sie erstellen ein neues Objekt in jeder iteration, dann ist das eine riesige Anzahl von Objekten. Sie wenig tun, außer, dass (nur eine Methode aufrufen, die hat einen trivialen operation). GC konnte noch Dominieren die insgesamt verbrachte Zeit.
  • es ist kein Problem mit den GC - da beide Fälle DIE GLEICHE ANZAHL VON ZUWEISUNGEN. Erste Programm nicht verwenden Schließung zweite Programm verwenden. Hast du jemals versucht zu verstehen, was die beiden Programme machen? Ich bin ganz damit einverstanden, dass viel Zeit damit verbracht wird, von GC, aber die gleiche Zeit in beiden Programmen! So ist dieses ständige Abweichung und keinen Unterschied, ob ich dies Messen mit warm-up oder mit nano - Messung. Nur zum Beweis meiner position, die ich gelegt habe, empfehlen Sie Google Bremssattel und warm-up! SIE KOMMENTARE SIND IRRELEVANT, weil die relative Anzahl der gleichzeitig x2 und x10.
  • Hast du eigentlich Messen der GC-overhead, oder sind Sie nur raten? Winkende Hände und schrie, dass GC mal das gleiche mit absolut keinen festen Beweis ist nicht der Weg zur Erleuchtung. Zuweisungen sind gemessen in bytes, nicht in der Zuteilung rechnen. Sie haben zumindest eine solide Beweis dafür, dass in beiden Fällen die gleiche Anzahl von bytes ist reserviert?
  • "Ich habe empfehlen Sie Google Bremssattel und warm-up!" --- Ich verstehe nicht diese Satz.
  • Vielleicht fehlt der Punkt, der meine Kommentare so weit: es ist die Fälschung einer Reihe von standard-Hypothesen über die häufigsten Fehlerquellen beim benchmarking auf der JVM. Nur wenn Sie die solide gelöscht, können Sie geben Sie eine ernsthafte Diskussion der Ergebnisse.
  • Beachten Sie, dass, neben der Tatsache, dass dieser "benchmark" ist weit entfernt von der beabsichtigten Anwendungsfall, nur die Angabe der -server option bei JVM-start wird die aufgenommene overhead gehen ganz Weg.
  • habe gerade versucht deine Empfehlung und bekommen genau das gleiche Ergebnis wie für reguläre JRE. Schließung in lambda langsamer als Verschluss für die anonyme Klasse in der Nähe der 10-mal.

InformationsquelleAutor Dewfy | 2013-09-25
Schreibe einen Kommentar