JSR – 310: Die Java 8 Date API auf dem Performance-Prüfstand

Eine der wichtigsten Neuerungen in Java 8 ist neben der Verwendung von Lambda-Ausdrücken die neue Date/Time API. Bisher kam häufig die Joda-Library bei Applikationen mit hohen Anforderungen an die Date/Time-Berechnung zum Einsatz. Die durch JSR-310 in Java 8 neu aufgenommene API soll diese Lücke nun im Standard JDK füllen. Die maßgeblichste Änderung neben der erneuerten API stellt die interne Datenrepräsentation dar. Die neuen Klassen folgen hierbei dem human time concept. Das bedeutet, dass die interne Repräsentation mit einzelnen Darstellungen für Tag, Monat, Jahr etc. implementiert wurde. Dies steht im Gegensatz zu dem bisherig verwendeten machine time concept (Darstellung über einen long-Wert) der Klassen des java.util Packages.

Was dies im Hinblick auf Performance bedeutet, wollen wir uns in einem kurzen ersten Test anschauen. Deutliche Performance-Unterschiede sind beim Erzeugen der Objekte und bei Additionen/Subtraktionen zu erwarten. Da diese auch häufige Operationen darstellen, haben wir uns für einen ersten Test diese Operationen herausgesucht.

Das erste Testszenarium erzeugt 10 Millionen Objekte mit einem vorbestimmten Datumswert. Eine Warm-up-Phase von 20.000 Schleifendurchläufen soll mögliche Nebeneffekte in der Startup-Phase abfangen.

public static void main (String [] args) {

    int repeatCount = 10000000;

    // warm up
    OldJavaJDK(20000);
    Java8JDK(20000);

    // measure
    SimpleTimer timer2=SimpleTimer.startTimer();        
    OldJavaJDK(repeatCount);
    timer2.stopTimer();

    SimpleTimer timer1=SimpleTimer.startTimer();
    Java8JDK(repeatCount);
    timer1.stopTimer();
}

private static void Java8JDK(int repeatCount) {
    for (int i=0; i<repeatCount; i++) {
        LocalDate christmas=LocalDate.of(2014,12,24); 
    }

}

private static void OldJavaJDK(int repeatCount) {
    for (int i=0; i<repeatCount; i++) {
        Calendar calendar=GregorianCalendar.getInstance();
        calendar.set(2014, 12, 24);
    }
}

Die Timer-Implementierung misst lediglich mit System.currentTimeMillis() die Zeit, welche zum Erzeugen der Objekte benötigt wurde.

Die Messergebnisse zeigen einen deutlichen Gewinn bei der Verwendung der neuen Klassen. Mit java.time.LocalDate werden 0 sec, 32 ms benötigt. Die bisherige Calendar-Implementierung java.util.GregorianCalender benötigt mit 2 sec, 375 ms deutlich länger.
Ebenso deutlich fällt der Unterschied bei der Addition/Subtraktion von Datumswerten aus.

private static void Java8JDK(int repeatCount) {
    LocalDate christmas=LocalDate.of(2014,12,24); 
    for (int i=0; i<repeatCount; i++) {
        christmas.plusDays(1);
    }
}

private static void OldJavaJDK(int repeatCount) {
    Calendar calendar=GregorianCalendar.getInstance();
    calendar.set(2014, 12, 24);

    for (int i=0; i<repeatCount; i++) {
        calendar.add(1, Calendar.DATE);
    }
}

Hier verlieren die bekannten Calendar-Klassen mit 6 sec, 138 ms deutlich gegen die Java 8 Neuerung (0 sec, 172 ms).

Als Fazit kann man schon nach diesem kurzen Test festhalten, dass das human time concept des neuen Java 8 Features in der Lage ist, die Performance bei den häufig verwendeten einfachen Datumsberechnungen zu verbessern. Die Messungen betreffen natürlich nur meine Hardware, verdeutlichen aber den Unterschied der beiden Implementierungen meiner Meinung nach bereits deutlich.

Interessant wären nun weitere ausgiebige Tests, wie sich die Performance zum Beispiel im Zusammenspiel mit Zeitzonen verhält.

Short URL for this post: http://wp.me/p4nxik-2gP
This entry was posted in Java Basics and tagged , , , , . Bookmark the permalink.

Leave a Reply