Last active
November 28, 2016 12:38
-
-
Save odrotbohm/487d58bd146a47574fb5a8316f950b04 to your computer and use it in GitHub Desktop.
Benchmark showing differences between formatting JDK 8 dates and legacy Date instances
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.sample; | |
import java.text.DateFormat; | |
import java.text.SimpleDateFormat; | |
import java.time.LocalDateTime; | |
import java.time.format.DateTimeFormatter; | |
import java.util.Date; | |
import java.util.TimeZone; | |
import org.openjdk.jmh.annotations.Benchmark; | |
import org.openjdk.jmh.annotations.Scope; | |
import org.openjdk.jmh.annotations.State; | |
public class MyBenchmark { | |
@State(Scope.Benchmark) | |
public static class LegacyDateState { | |
private final DateFormat format; | |
private final Date date; | |
public LegacyDateState() { | |
this.format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); | |
this.format.setTimeZone(TimeZone.getTimeZone("UTC")); | |
this.date = new Date(); | |
} | |
} | |
@State(Scope.Benchmark) | |
public static class Jdk8DateState { | |
volatile LocalDateTime now = LocalDateTime.now(); | |
volatile DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); | |
} | |
@State(Scope.Benchmark) | |
public static class Jdk8DateStateWithConstant { | |
volatile LocalDateTime now = LocalDateTime.now(); | |
volatile DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME; | |
} | |
@Benchmark | |
public void formatLegacyDate(LegacyDateState state) { | |
state.format.format(state.date); | |
} | |
@Benchmark | |
public void formatJdk8Date(Jdk8DateState state) { | |
state.formatter.format(state.now); | |
} | |
@Benchmark | |
public void formatJdk8DateWithConstant(Jdk8DateStateWithConstant state) { | |
state.formatter.format(state.now); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ java -jar target/benchmarks.jar -wi 10 -i 10 -f 3 | |
# JMH 1.16 (released 17 days ago) | |
# VM version: JDK 1.8.0_112, VM 25.112-b16 | |
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre/bin/java | |
# VM options: <none> | |
# Warmup: 10 iterations, 1 s each | |
# Measurement: 10 iterations, 1 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Throughput, ops/time | |
# Benchmark: org.sample.MyBenchmark.formatJdk8Date | |
# Run progress: 0,00% complete, ETA 00:03:00 | |
# Fork: 1 of 3 | |
# Warmup Iteration 1: 1684192,789 ops/s | |
# Warmup Iteration 2: 1686202,091 ops/s | |
# Warmup Iteration 3: 1464344,370 ops/s | |
# Warmup Iteration 4: 1759962,170 ops/s | |
# Warmup Iteration 5: 1994955,274 ops/s | |
# Warmup Iteration 6: 2102568,510 ops/s | |
# Warmup Iteration 7: 2095488,529 ops/s | |
# Warmup Iteration 8: 2108256,666 ops/s | |
# Warmup Iteration 9: 2111502,802 ops/s | |
# Warmup Iteration 10: 1418172,189 ops/s | |
Iteration 1: 1997149,166 ops/s | |
Iteration 2: 2111866,469 ops/s | |
Iteration 3: 2140621,185 ops/s | |
Iteration 4: 2100821,614 ops/s | |
Iteration 5: 2121535,606 ops/s | |
Iteration 6: 2028756,643 ops/s | |
Iteration 7: 1701779,072 ops/s | |
Iteration 8: 2014830,453 ops/s | |
Iteration 9: 2061489,624 ops/s | |
Iteration 10: 1954533,519 ops/s | |
# Run progress: 11,11% complete, ETA 00:02:45 | |
# Fork: 2 of 3 | |
# Warmup Iteration 1: 1416393,987 ops/s | |
# Warmup Iteration 2: 1733252,638 ops/s | |
# Warmup Iteration 3: 1680686,365 ops/s | |
# Warmup Iteration 4: 1978360,537 ops/s | |
# Warmup Iteration 5: 2013851,481 ops/s | |
# Warmup Iteration 6: 2034086,186 ops/s | |
# Warmup Iteration 7: 1985682,880 ops/s | |
# Warmup Iteration 8: 1736872,111 ops/s | |
# Warmup Iteration 9: 2026089,664 ops/s | |
# Warmup Iteration 10: 1531258,871 ops/s | |
Iteration 1: 1558250,045 ops/s | |
Iteration 2: 1869779,437 ops/s | |
Iteration 3: 2022251,593 ops/s | |
Iteration 4: 2017906,258 ops/s | |
Iteration 5: 2025278,466 ops/s | |
Iteration 6: 1985557,002 ops/s | |
Iteration 7: 1362722,742 ops/s | |
Iteration 8: 1251507,524 ops/s | |
Iteration 9: 1655907,024 ops/s | |
Iteration 10: 1932596,109 ops/s | |
# Run progress: 22,22% complete, ETA 00:02:24 | |
# Fork: 3 of 3 | |
# Warmup Iteration 1: 1188103,490 ops/s | |
# Warmup Iteration 2: 1761795,965 ops/s | |
# Warmup Iteration 3: 1588427,057 ops/s | |
# Warmup Iteration 4: 1630942,379 ops/s | |
# Warmup Iteration 5: 1990693,450 ops/s | |
# Warmup Iteration 6: 1977035,232 ops/s | |
# Warmup Iteration 7: 1974555,591 ops/s | |
# Warmup Iteration 8: 2062885,267 ops/s | |
# Warmup Iteration 9: 1956363,451 ops/s | |
# Warmup Iteration 10: 1665759,371 ops/s | |
Iteration 1: 1444716,229 ops/s | |
Iteration 2: 1894498,774 ops/s | |
Iteration 3: 2053270,523 ops/s | |
Iteration 4: 2056347,853 ops/s | |
Iteration 5: 2008202,462 ops/s | |
Iteration 6: 2053475,444 ops/s | |
Iteration 7: 1401129,059 ops/s | |
Iteration 8: 1773503,351 ops/s | |
Iteration 9: 2017938,564 ops/s | |
Iteration 10: 1972053,954 ops/s | |
Result "formatJdk8Date": | |
1886342,526 ±(99.9%) 166823,201 ops/s [Average] | |
(min, avg, max) = (1251507,524, 1886342,526, 2140621,185), stdev = 249693,132 | |
CI (99.9%): [1719519,325, 2053165,726] (assumes normal distribution) | |
# JMH 1.16 (released 17 days ago) | |
# VM version: JDK 1.8.0_112, VM 25.112-b16 | |
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre/bin/java | |
# VM options: <none> | |
# Warmup: 10 iterations, 1 s each | |
# Measurement: 10 iterations, 1 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Throughput, ops/time | |
# Benchmark: org.sample.MyBenchmark.formatJdk8DateWithConstant | |
# Run progress: 33,33% complete, ETA 00:02:03 | |
# Fork: 1 of 3 | |
# Warmup Iteration 1: 259264,260 ops/s | |
# Warmup Iteration 2: 309792,258 ops/s | |
# Warmup Iteration 3: 299717,069 ops/s | |
# Warmup Iteration 4: 335683,471 ops/s | |
# Warmup Iteration 5: 356124,256 ops/s | |
# Warmup Iteration 6: 364178,229 ops/s | |
# Warmup Iteration 7: 368815,564 ops/s | |
# Warmup Iteration 8: 372435,154 ops/s | |
# Warmup Iteration 9: 349236,714 ops/s | |
# Warmup Iteration 10: 289359,626 ops/s | |
Iteration 1: 328938,994 ops/s | |
Iteration 2: 286539,935 ops/s | |
Iteration 3: 368033,224 ops/s | |
Iteration 4: 345386,619 ops/s | |
Iteration 5: 365218,450 ops/s | |
Iteration 6: 352205,647 ops/s | |
Iteration 7: 314011,655 ops/s | |
Iteration 8: 367909,510 ops/s | |
Iteration 9: 386295,095 ops/s | |
Iteration 10: 382388,971 ops/s | |
# Run progress: 44,44% complete, ETA 00:01:43 | |
# Fork: 2 of 3 | |
# Warmup Iteration 1: 274785,956 ops/s | |
# Warmup Iteration 2: 261040,612 ops/s | |
# Warmup Iteration 3: 278998,742 ops/s | |
# Warmup Iteration 4: 356453,013 ops/s | |
# Warmup Iteration 5: 374929,084 ops/s | |
# Warmup Iteration 6: 370160,348 ops/s | |
# Warmup Iteration 7: 374745,342 ops/s | |
# Warmup Iteration 8: 381081,191 ops/s | |
# Warmup Iteration 9: 370130,363 ops/s | |
# Warmup Iteration 10: 329296,221 ops/s | |
Iteration 1: 367806,437 ops/s | |
Iteration 2: 373774,662 ops/s | |
Iteration 3: 371254,588 ops/s | |
Iteration 4: 320872,273 ops/s | |
Iteration 5: 353666,236 ops/s | |
Iteration 6: 306398,556 ops/s | |
Iteration 7: 357973,373 ops/s | |
Iteration 8: 406654,190 ops/s | |
Iteration 9: 403319,415 ops/s | |
Iteration 10: 409396,011 ops/s | |
# Run progress: 55,56% complete, ETA 00:01:22 | |
# Fork: 3 of 3 | |
# Warmup Iteration 1: 265749,479 ops/s | |
# Warmup Iteration 2: 255471,703 ops/s | |
# Warmup Iteration 3: 214959,264 ops/s | |
# Warmup Iteration 4: 293742,177 ops/s | |
# Warmup Iteration 5: 306066,527 ops/s | |
# Warmup Iteration 6: 292562,147 ops/s | |
# Warmup Iteration 7: 296701,359 ops/s | |
# Warmup Iteration 8: 294786,427 ops/s | |
# Warmup Iteration 9: 294343,792 ops/s | |
# Warmup Iteration 10: 270318,195 ops/s | |
Iteration 1: 253292,748 ops/s | |
Iteration 2: 307244,102 ops/s | |
Iteration 3: 295886,576 ops/s | |
Iteration 4: 305620,518 ops/s | |
Iteration 5: 292690,097 ops/s | |
Iteration 6: 278443,058 ops/s | |
Iteration 7: 244879,827 ops/s | |
Iteration 8: 294855,005 ops/s | |
Iteration 9: 312867,369 ops/s | |
Iteration 10: 312401,455 ops/s | |
Result "formatJdk8DateWithConstant": | |
335540,820 ±(99.9%) 29845,868 ops/s [Average] | |
(min, avg, max) = (244879,827, 335540,820, 409396,011), stdev = 44671,893 | |
CI (99.9%): [305694,952, 365386,687] (assumes normal distribution) | |
# JMH 1.16 (released 17 days ago) | |
# VM version: JDK 1.8.0_112, VM 25.112-b16 | |
# VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/jre/bin/java | |
# VM options: <none> | |
# Warmup: 10 iterations, 1 s each | |
# Measurement: 10 iterations, 1 s each | |
# Timeout: 10 min per iteration | |
# Threads: 1 thread, will synchronize iterations | |
# Benchmark mode: Throughput, ops/time | |
# Benchmark: org.sample.MyBenchmark.formatLegacyDate | |
# Run progress: 66,67% complete, ETA 00:01:01 | |
# Fork: 1 of 3 | |
# Warmup Iteration 1: 558908,887 ops/s | |
# Warmup Iteration 2: 733246,803 ops/s | |
# Warmup Iteration 3: 654824,263 ops/s | |
# Warmup Iteration 4: 970764,418 ops/s | |
# Warmup Iteration 5: 1876089,024 ops/s | |
# Warmup Iteration 6: 1882206,197 ops/s | |
# Warmup Iteration 7: 1877363,617 ops/s | |
# Warmup Iteration 8: 1858094,838 ops/s | |
# Warmup Iteration 9: 1878924,724 ops/s | |
# Warmup Iteration 10: 1789864,746 ops/s | |
Iteration 1: 1668166,021 ops/s | |
Iteration 2: 1803687,883 ops/s | |
Iteration 3: 1873987,624 ops/s | |
Iteration 4: 1487915,597 ops/s | |
Iteration 5: 1752674,668 ops/s | |
Iteration 6: 1786828,395 ops/s | |
Iteration 7: 1565108,237 ops/s | |
Iteration 8: 1787501,500 ops/s | |
Iteration 9: 1940318,219 ops/s | |
Iteration 10: 1912371,359 ops/s | |
# Run progress: 77,78% complete, ETA 00:00:41 | |
# Fork: 2 of 3 | |
# Warmup Iteration 1: 599469,734 ops/s | |
# Warmup Iteration 2: 749705,562 ops/s | |
# Warmup Iteration 3: 742123,698 ops/s | |
# Warmup Iteration 4: 694818,481 ops/s | |
# Warmup Iteration 5: 1716543,122 ops/s | |
# Warmup Iteration 6: 1920223,205 ops/s | |
# Warmup Iteration 7: 1888521,835 ops/s | |
# Warmup Iteration 8: 1943699,556 ops/s | |
# Warmup Iteration 9: 1899301,137 ops/s | |
# Warmup Iteration 10: 1715226,998 ops/s | |
Iteration 1: 1659789,851 ops/s | |
Iteration 2: 1617006,970 ops/s | |
Iteration 3: 1892000,346 ops/s | |
Iteration 4: 1881957,686 ops/s | |
Iteration 5: 1730584,294 ops/s | |
Iteration 6: 1910522,703 ops/s | |
Iteration 7: 1567944,026 ops/s | |
Iteration 8: 1669108,620 ops/s | |
Iteration 9: 1756863,430 ops/s | |
Iteration 10: 1579308,134 ops/s | |
# Run progress: 88,89% complete, ETA 00:00:20 | |
# Fork: 3 of 3 | |
# Warmup Iteration 1: 535643,751 ops/s | |
# Warmup Iteration 2: 645546,644 ops/s | |
# Warmup Iteration 3: 663993,474 ops/s | |
# Warmup Iteration 4: 823116,005 ops/s | |
# Warmup Iteration 5: 1274272,854 ops/s | |
# Warmup Iteration 6: 1783957,934 ops/s | |
# Warmup Iteration 7: 1877934,541 ops/s | |
# Warmup Iteration 8: 1916655,841 ops/s | |
# Warmup Iteration 9: 1938060,232 ops/s | |
# Warmup Iteration 10: 1788800,558 ops/s | |
Iteration 1: 1693860,214 ops/s | |
Iteration 2: 1834989,508 ops/s | |
Iteration 3: 1812320,658 ops/s | |
Iteration 4: 1838640,784 ops/s | |
Iteration 5: 1634193,379 ops/s | |
Iteration 6: 1758847,144 ops/s | |
Iteration 7: 1738058,690 ops/s | |
Iteration 8: 1666883,116 ops/s | |
Iteration 9: 1827605,405 ops/s | |
Iteration 10: 1878504,576 ops/s | |
Result "formatLegacyDate": | |
1750918,301 ±(99.9%) 80093,337 ops/s [Average] | |
(min, avg, max) = (1487915,597, 1750918,301, 1940318,219), stdev = 119879,946 | |
CI (99.9%): [1670824,964, 1831011,639] (assumes normal distribution) | |
# Run complete. Total time: 00:03:05 | |
Benchmark Mode Cnt Score Error Units | |
MyBenchmark.formatJdk8Date thrpt 30 1886342,526 ± 166823,201 ops/s | |
MyBenchmark.formatJdk8DateWithConstant thrpt 30 335540,820 ± 29845,868 ops/s | |
MyBenchmark.formatLegacyDate thrpt 30 1750918,301 ± 80093,337 ops/s |
Any idea why?
DateTimeFormatter.ISO_LOCAL_DATE_TIME
is a lot faster that DateTimeFormatter.ISO_DATE_TIME
:
Benchmark Mode Cnt Score Error Units
MyBenchmark.formatJdk8Date thrpt 30 2212442,038 ± 44622,371 ops/s
MyBenchmark.formatJdk8DateWithConstant thrpt 30 238294,704 ± 13061,266 ops/s
MyBenchmark.formatJdk8DateWithConstantLocal thrpt 30 2019639,192 ± 168394,350 ops/s
MyBenchmark.formatLegacyDate thrpt 30 1581412,174 ± 80028,387 ops/s
It looks like the offset and zone handling in DateTimeFormatter.ISO_DATE_TIME
causes the slowdown.
Actually it's the combination of LocalDateTime
and DateTimeFormatter.ISO_DATE_TIME
. If you use ZonedDateTime
instead, it gets a lot faster. So if you use LocalDateTime
, you should also use DateTimeFormatter.ISO_LOCAL_DATE_TIME
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It looks like changing the setup of the JDK 8
DateTimeFormatter
to rather useDateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'")
significantly improves the numbers ever to the benefit of JDK 8: