Java 11 — performance regressions against Java 8?
UPDATE: Seeing as each method might be suffering from a different performance issue I decided to split this question into two:
- Empty methods noticeably slower in Java 11 than Java 8
- Consuming stack traces noticeably slower in Java 11 than Java 8
The original discussion can be found below...
I was comparing my library's performance under Java 8 and 11 when I ran across some surprising numbers. Here is the benchmark code:
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.infra.Blackhole;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark
{
@Benchmark
public void emptyMethod()
{
}
@Benchmark
public void throwAndConsumeStacktrace(Blackhole bh)
{
try
{
throw new IllegalArgumentException("I love benchmarks");
}
catch (IllegalArgumentException e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
bh.consume(sw.toString());
}
}
}
Running with jmh 1.21, OracleJDK 1.8.0_192 returns:
MyBenchmark.emptyMethod avgt 25 0.363 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 21408.072 ± 127.393 ns/op
OracleJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.759 ± 0.034 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47143.168 ± 1346.898 ns/op
OpenJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.725 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47389.051 ± 994.345 ns/op
Granted, the absolute difference for emptyMethod() is tiny but the trend seems to follow for more expensive operations like throwAndConsumeStacktrace(). As an aside, other operations (such as throwing exceptions and never consuming their stacktrace) are only moderately slower in Java 11 so the performance drop does not apply across all operations.
I understand that microbenchmarks do not indicate the performance behavior of real-life applications. Still, I'm curious where this difference is coming from. Any ideas?
Here is the full version info for the JDKs I used:
OracleJDK 8:
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
OracleJDK 11.0.1:
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
OpenJDK 11.0.1:
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
performance java-8 java-11 microbenchmark jmh
|
show 9 more comments
UPDATE: Seeing as each method might be suffering from a different performance issue I decided to split this question into two:
- Empty methods noticeably slower in Java 11 than Java 8
- Consuming stack traces noticeably slower in Java 11 than Java 8
The original discussion can be found below...
I was comparing my library's performance under Java 8 and 11 when I ran across some surprising numbers. Here is the benchmark code:
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.infra.Blackhole;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark
{
@Benchmark
public void emptyMethod()
{
}
@Benchmark
public void throwAndConsumeStacktrace(Blackhole bh)
{
try
{
throw new IllegalArgumentException("I love benchmarks");
}
catch (IllegalArgumentException e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
bh.consume(sw.toString());
}
}
}
Running with jmh 1.21, OracleJDK 1.8.0_192 returns:
MyBenchmark.emptyMethod avgt 25 0.363 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 21408.072 ± 127.393 ns/op
OracleJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.759 ± 0.034 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47143.168 ± 1346.898 ns/op
OpenJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.725 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47389.051 ± 994.345 ns/op
Granted, the absolute difference for emptyMethod() is tiny but the trend seems to follow for more expensive operations like throwAndConsumeStacktrace(). As an aside, other operations (such as throwing exceptions and never consuming their stacktrace) are only moderately slower in Java 11 so the performance drop does not apply across all operations.
I understand that microbenchmarks do not indicate the performance behavior of real-life applications. Still, I'm curious where this difference is coming from. Any ideas?
Here is the full version info for the JDKs I used:
OracleJDK 8:
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
OracleJDK 11.0.1:
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
OpenJDK 11.0.1:
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
performance java-8 java-11 microbenchmark jmh
4
Though I am not good at JMH. Yet, trying out few things, what further puzzles me now is that when I separated out thewriters to a different method and ignored the exception. Java-11 stats came up better than Java-8. Maybe just running the benchmark withbh.consume(e.toString());could clear out the picture here. Would give it a try in sometime to confirm.
– nullpointer
Dec 29 '18 at 7:34
6
You might want to try catching IAE with an empty catch block to see if throwing the exception has really regressed. It may be that printStackTrace is more expensive in JDK 9 and newer as the output is a bit more complicated.
– Alan Bateman
Dec 29 '18 at 7:35
3
@AlanBateman I could confirm running the benchmark for ignoring the exception. The results were quite similar for both the JDK version at least for me. I would though insist Gili to give it a try by himself and come back with the exact results.
– nullpointer
Dec 29 '18 at 7:37
3
Thanks for checking, can you now add a benchmark for Throwable::toString to see whether e.printStackTrace is the real difference in the original benchmark.
– Alan Bateman
Dec 29 '18 at 7:44
2
Possible duplicate of Empty methods noticeably slower in Java 11 than Java 8
– Strom
Jan 3 at 23:50
|
show 9 more comments
UPDATE: Seeing as each method might be suffering from a different performance issue I decided to split this question into two:
- Empty methods noticeably slower in Java 11 than Java 8
- Consuming stack traces noticeably slower in Java 11 than Java 8
The original discussion can be found below...
I was comparing my library's performance under Java 8 and 11 when I ran across some surprising numbers. Here is the benchmark code:
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.infra.Blackhole;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark
{
@Benchmark
public void emptyMethod()
{
}
@Benchmark
public void throwAndConsumeStacktrace(Blackhole bh)
{
try
{
throw new IllegalArgumentException("I love benchmarks");
}
catch (IllegalArgumentException e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
bh.consume(sw.toString());
}
}
}
Running with jmh 1.21, OracleJDK 1.8.0_192 returns:
MyBenchmark.emptyMethod avgt 25 0.363 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 21408.072 ± 127.393 ns/op
OracleJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.759 ± 0.034 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47143.168 ± 1346.898 ns/op
OpenJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.725 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47389.051 ± 994.345 ns/op
Granted, the absolute difference for emptyMethod() is tiny but the trend seems to follow for more expensive operations like throwAndConsumeStacktrace(). As an aside, other operations (such as throwing exceptions and never consuming their stacktrace) are only moderately slower in Java 11 so the performance drop does not apply across all operations.
I understand that microbenchmarks do not indicate the performance behavior of real-life applications. Still, I'm curious where this difference is coming from. Any ideas?
Here is the full version info for the JDKs I used:
OracleJDK 8:
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
OracleJDK 11.0.1:
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
OpenJDK 11.0.1:
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
performance java-8 java-11 microbenchmark jmh
UPDATE: Seeing as each method might be suffering from a different performance issue I decided to split this question into two:
- Empty methods noticeably slower in Java 11 than Java 8
- Consuming stack traces noticeably slower in Java 11 than Java 8
The original discussion can be found below...
I was comparing my library's performance under Java 8 and 11 when I ran across some surprising numbers. Here is the benchmark code:
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.infra.Blackhole;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark
{
@Benchmark
public void emptyMethod()
{
}
@Benchmark
public void throwAndConsumeStacktrace(Blackhole bh)
{
try
{
throw new IllegalArgumentException("I love benchmarks");
}
catch (IllegalArgumentException e)
{
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
bh.consume(sw.toString());
}
}
}
Running with jmh 1.21, OracleJDK 1.8.0_192 returns:
MyBenchmark.emptyMethod avgt 25 0.363 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 21408.072 ± 127.393 ns/op
OracleJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.759 ± 0.034 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47143.168 ± 1346.898 ns/op
OpenJDK 11.0.1 returns:
Benchmark Mode Cnt Score Error Units
MyBenchmark.emptyMethod avgt 25 0.725 ± 0.001 ns/op
MyBenchmark.throwAndConsumeStacktrace avgt 25 47389.051 ± 994.345 ns/op
Granted, the absolute difference for emptyMethod() is tiny but the trend seems to follow for more expensive operations like throwAndConsumeStacktrace(). As an aside, other operations (such as throwing exceptions and never consuming their stacktrace) are only moderately slower in Java 11 so the performance drop does not apply across all operations.
I understand that microbenchmarks do not indicate the performance behavior of real-life applications. Still, I'm curious where this difference is coming from. Any ideas?
Here is the full version info for the JDKs I used:
OracleJDK 8:
java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
OracleJDK 11.0.1:
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
OpenJDK 11.0.1:
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
performance java-8 java-11 microbenchmark jmh
performance java-8 java-11 microbenchmark jmh
edited Jan 6 at 20:25
Brian Goetz
56.4k1399116
56.4k1399116
asked Dec 28 '18 at 16:10
GiliGili
40.3k61272513
40.3k61272513
4
Though I am not good at JMH. Yet, trying out few things, what further puzzles me now is that when I separated out thewriters to a different method and ignored the exception. Java-11 stats came up better than Java-8. Maybe just running the benchmark withbh.consume(e.toString());could clear out the picture here. Would give it a try in sometime to confirm.
– nullpointer
Dec 29 '18 at 7:34
6
You might want to try catching IAE with an empty catch block to see if throwing the exception has really regressed. It may be that printStackTrace is more expensive in JDK 9 and newer as the output is a bit more complicated.
– Alan Bateman
Dec 29 '18 at 7:35
3
@AlanBateman I could confirm running the benchmark for ignoring the exception. The results were quite similar for both the JDK version at least for me. I would though insist Gili to give it a try by himself and come back with the exact results.
– nullpointer
Dec 29 '18 at 7:37
3
Thanks for checking, can you now add a benchmark for Throwable::toString to see whether e.printStackTrace is the real difference in the original benchmark.
– Alan Bateman
Dec 29 '18 at 7:44
2
Possible duplicate of Empty methods noticeably slower in Java 11 than Java 8
– Strom
Jan 3 at 23:50
|
show 9 more comments
4
Though I am not good at JMH. Yet, trying out few things, what further puzzles me now is that when I separated out thewriters to a different method and ignored the exception. Java-11 stats came up better than Java-8. Maybe just running the benchmark withbh.consume(e.toString());could clear out the picture here. Would give it a try in sometime to confirm.
– nullpointer
Dec 29 '18 at 7:34
6
You might want to try catching IAE with an empty catch block to see if throwing the exception has really regressed. It may be that printStackTrace is more expensive in JDK 9 and newer as the output is a bit more complicated.
– Alan Bateman
Dec 29 '18 at 7:35
3
@AlanBateman I could confirm running the benchmark for ignoring the exception. The results were quite similar for both the JDK version at least for me. I would though insist Gili to give it a try by himself and come back with the exact results.
– nullpointer
Dec 29 '18 at 7:37
3
Thanks for checking, can you now add a benchmark for Throwable::toString to see whether e.printStackTrace is the real difference in the original benchmark.
– Alan Bateman
Dec 29 '18 at 7:44
2
Possible duplicate of Empty methods noticeably slower in Java 11 than Java 8
– Strom
Jan 3 at 23:50
4
4
Though I am not good at JMH. Yet, trying out few things, what further puzzles me now is that when I separated out the
writers to a different method and ignored the exception. Java-11 stats came up better than Java-8. Maybe just running the benchmark with bh.consume(e.toString()); could clear out the picture here. Would give it a try in sometime to confirm.– nullpointer
Dec 29 '18 at 7:34
Though I am not good at JMH. Yet, trying out few things, what further puzzles me now is that when I separated out the
writers to a different method and ignored the exception. Java-11 stats came up better than Java-8. Maybe just running the benchmark with bh.consume(e.toString()); could clear out the picture here. Would give it a try in sometime to confirm.– nullpointer
Dec 29 '18 at 7:34
6
6
You might want to try catching IAE with an empty catch block to see if throwing the exception has really regressed. It may be that printStackTrace is more expensive in JDK 9 and newer as the output is a bit more complicated.
– Alan Bateman
Dec 29 '18 at 7:35
You might want to try catching IAE with an empty catch block to see if throwing the exception has really regressed. It may be that printStackTrace is more expensive in JDK 9 and newer as the output is a bit more complicated.
– Alan Bateman
Dec 29 '18 at 7:35
3
3
@AlanBateman I could confirm running the benchmark for ignoring the exception. The results were quite similar for both the JDK version at least for me. I would though insist Gili to give it a try by himself and come back with the exact results.
– nullpointer
Dec 29 '18 at 7:37
@AlanBateman I could confirm running the benchmark for ignoring the exception. The results were quite similar for both the JDK version at least for me. I would though insist Gili to give it a try by himself and come back with the exact results.
– nullpointer
Dec 29 '18 at 7:37
3
3
Thanks for checking, can you now add a benchmark for Throwable::toString to see whether e.printStackTrace is the real difference in the original benchmark.
– Alan Bateman
Dec 29 '18 at 7:44
Thanks for checking, can you now add a benchmark for Throwable::toString to see whether e.printStackTrace is the real difference in the original benchmark.
– Alan Bateman
Dec 29 '18 at 7:44
2
2
Possible duplicate of Empty methods noticeably slower in Java 11 than Java 8
– Strom
Jan 3 at 23:50
Possible duplicate of Empty methods noticeably slower in Java 11 than Java 8
– Strom
Jan 3 at 23:50
|
show 9 more comments
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53961275%2fjava-11-performance-regressions-against-java-8%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53961275%2fjava-11-performance-regressions-against-java-8%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
Though I am not good at JMH. Yet, trying out few things, what further puzzles me now is that when I separated out the
writers to a different method and ignored the exception. Java-11 stats came up better than Java-8. Maybe just running the benchmark withbh.consume(e.toString());could clear out the picture here. Would give it a try in sometime to confirm.– nullpointer
Dec 29 '18 at 7:34
6
You might want to try catching IAE with an empty catch block to see if throwing the exception has really regressed. It may be that printStackTrace is more expensive in JDK 9 and newer as the output is a bit more complicated.
– Alan Bateman
Dec 29 '18 at 7:35
3
@AlanBateman I could confirm running the benchmark for ignoring the exception. The results were quite similar for both the JDK version at least for me. I would though insist Gili to give it a try by himself and come back with the exact results.
– nullpointer
Dec 29 '18 at 7:37
3
Thanks for checking, can you now add a benchmark for Throwable::toString to see whether e.printStackTrace is the real difference in the original benchmark.
– Alan Bateman
Dec 29 '18 at 7:44
2
Possible duplicate of Empty methods noticeably slower in Java 11 than Java 8
– Strom
Jan 3 at 23:50