Java 11 -- performance regressions against Java 8?

PerformanceJava 8Java 11MicrobenchmarkJmh

Performance Problem Overview


UPDATE: Seeing as each method might be suffering from a different performance issue I decided to split this question into two:

  1. https://stackoverflow.com/q/54001417/14731
  2. https://stackoverflow.com/q/54008778/14731

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 Solutions


Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGiliView Question on Stackoverflow