undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
61
test/benchmarks/micros-javac/README.md
Normal file
61
test/benchmarks/micros-javac/README.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Javac microbenchmarks
|
||||
|
||||
The Javac Microbenchmarks is a collection of microbenchmarks for measuring
|
||||
the performance of Javac API using the
|
||||
[JMH](http://openjdk.java.net/projects/code-tools/jmh/) framework.
|
||||
|
||||
|
||||
## Building and running the project
|
||||
|
||||
Currently, the project can be built and run with JDK 9 and later. This is
|
||||
a Maven project and is built by:
|
||||
|
||||
$ mvn clean install
|
||||
|
||||
After building, the executable jar is target/micros-javac-[version].jar.
|
||||
Run the benchmarks with:
|
||||
|
||||
$ java -jar target/micros-javac-*.jar [optional jmh parameters]
|
||||
|
||||
See the entire list of benchmarks using:
|
||||
|
||||
$ java -jar target/micros-javacs-*.jar -l [optional regex to select benchmarks]
|
||||
|
||||
For example:
|
||||
|
||||
$ java -jar target/micros-javac-1.0-SNAPSHOT.jar -l
|
||||
Benchmarks:
|
||||
org.openjdk.bench.langtools.javac.GroupJavacBenchmark.coldGroup
|
||||
org.openjdk.bench.langtools.javac.GroupJavacBenchmark.hotGroup
|
||||
org.openjdk.bench.langtools.javac.SingleJavacBenchmark.compileCold
|
||||
org.openjdk.bench.langtools.javac.SingleJavacBenchmark.compileHot
|
||||
|
||||
And the same regex syntax works to run some test:
|
||||
|
||||
$ java -jar target/micros-javac-1.0-SNAPSHOT.jar SingleJavacBenchmark.compileHot
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build of micros-javac module got stuck
|
||||
|
||||
If you build got stuck on `[get] Getting: https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip` then you are probably experiencing some networking or web proxy obstacles.
|
||||
|
||||
One solution is to download required reference JDK from [https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip](https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip) manually and then build the project with property pointing to the local copy:
|
||||
|
||||
$ mvn clean install -Djavac.benchmark.openjdk.zip.download.url=file:///<your download location>/openjdk-11+28_windows-x64_bin.zip
|
||||
|
||||
Note: Please use `openjdk-11+28_windows-x64_bin.zip` to build the project no matter what target platform is.
|
||||
|
||||
Another solution might be to add proxy settings:
|
||||
|
||||
$ mvn -Dhttps.proxyHost=... -Dhttps.proxyPort=... clean install
|
||||
|
||||
### Execution of micros-javac benchmarks takes several hours
|
||||
|
||||
micros-javac benchmarks consist of two sets of benchmarks:
|
||||
* `SingleJavacBenchmark` (which is parametrized) measures each single javac compilation stage in an isolated run. This benchmark is designed for exact automated performance regression testing and it takes several hours to execute completely.
|
||||
* `GroupJavacBenchmark` is grouping the measurements of all javac compilation stages into one run and its execution should take less than 30 minutes on a regular developers computer.
|
||||
|
||||
Solution to speed up javac benchmarking is to select only `GroupJavacBenchmark` for execution using following command line:
|
||||
|
||||
$ java -jar target/micros-javac-1.0-SNAPSHOT.jar .*GroupJavacBenchmark.*
|
||||
145
test/benchmarks/micros-javac/pom.xml
Normal file
145
test/benchmarks/micros-javac/pom.xml
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<!--
|
||||
Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
|
||||
This code is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License version 2 only, as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
version 2 for more details (a copy is included in the LICENSE file that
|
||||
accompanied this code).
|
||||
|
||||
You should have received a copy of the GNU General Public License version
|
||||
2 along with this work; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
or visit www.oracle.com if you need additional information or have any
|
||||
questions.
|
||||
-->
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.openjdk</groupId>
|
||||
<artifactId>micros-javac</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>OpenJDK Microbenchmark of Java Compile</name>
|
||||
<properties>
|
||||
<!--
|
||||
the code below is being compiled with source 25, see JDK-8372023,
|
||||
if the source version being compiled changes to 26 or 26+, then
|
||||
some adjustments will be needed at:
|
||||
test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/JavacBenchmark.java
|
||||
-->
|
||||
<javac.benchmark.openjdk.zip.download.url>https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip</javac.benchmark.openjdk.zip.download.url>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<jmh.version>1.36</jmh.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>org.openjdk.jmh.Main</mainClass>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/BenchmarkList</resource>
|
||||
</transformer>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/CompilerHints</resource>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.14.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.1.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<mkdir dir="${project.build.outputDirectory}"/>
|
||||
<get src="${javac.benchmark.openjdk.zip.download.url}" dest="${project.build.directory}/jdk-bin.zip" skipexisting="true" verbose="true"/>
|
||||
<unzip src="${project.build.directory}/jdk-bin.zip" dest="${project.build.outputDirectory}">
|
||||
<patternset>
|
||||
<include name="*/lib/src.zip"/>
|
||||
<include name="*/release"/>
|
||||
</patternset>
|
||||
<mapper type="flatten"/>
|
||||
</unzip>
|
||||
<loadfile srcFile="${project.build.outputDirectory}/release" property="release.info"/>
|
||||
<echo>
|
||||
-------------------------------------------------
|
||||
Bundling JDK sources with following release info:
|
||||
-------------------------------------------------
|
||||
${release.info}
|
||||
-------------------------------------------------
|
||||
</echo>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.bench.langtools.javac;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Group;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public class GroupJavacBenchmark extends JavacBenchmark {
|
||||
|
||||
public static final String COLD_GROUP_NAME = "coldGroup";
|
||||
public static final int COLD_ITERATION_WARMUPS = 0;
|
||||
public static final int COLD_ITERATIONS = 1;
|
||||
public static final int COLD_FORK_WARMUPS = 1;
|
||||
public static final int COLD_FORKS = 15;
|
||||
|
||||
public static final String HOT_GROUP_NAME = "hotGroup";
|
||||
public static final int HOT_ITERATION_WARMUPS = 8;
|
||||
public static final int HOT_ITERATIONS = 10;
|
||||
public static final int HOT_FORK_WARMUPS = 0;
|
||||
public static final int HOT_FORKS = 1;
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold1_Init() throws InterruptedException {
|
||||
Stage.Init.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold2_Parse() throws InterruptedException {
|
||||
Stage.Parse.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold3_InitModules() throws InterruptedException {
|
||||
Stage.InitModules.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold4_Enter() throws InterruptedException {
|
||||
Stage.Enter.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold5_Attribute() throws InterruptedException {
|
||||
Stage.Attribute.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold6_Flow() throws InterruptedException {
|
||||
Stage.Flow.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold7_Desugar() throws InterruptedException {
|
||||
Stage.Desugar.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(COLD_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = COLD_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = COLD_ITERATIONS)
|
||||
@Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void cold8_Generate(Blackhole bh) throws IOException {
|
||||
compile(bh, Stage.Generate);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot1_Init() throws InterruptedException {
|
||||
Stage.Init.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot2_Parse() throws InterruptedException {
|
||||
Stage.Parse.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot3_InitModules() throws InterruptedException {
|
||||
Stage.InitModules.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot4_Enter() throws InterruptedException {
|
||||
Stage.Enter.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot5_Attribute() throws InterruptedException {
|
||||
Stage.Attribute.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot6_Flow() throws InterruptedException {
|
||||
Stage.Flow.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot7_Desugar() throws InterruptedException {
|
||||
Stage.Desugar.waitFor();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Group(HOT_GROUP_NAME)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = HOT_ITERATION_WARMUPS)
|
||||
@Measurement(iterations = HOT_ITERATIONS)
|
||||
@Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void hot8_Generate(Blackhole bh) throws IOException {
|
||||
compile(bh, Stage.Generate);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.bench.langtools.javac;
|
||||
|
||||
import com.sun.tools.javac.comp.AttrContext;
|
||||
import com.sun.tools.javac.comp.Env;
|
||||
import com.sun.tools.javac.file.JavacFileManager;
|
||||
import com.sun.tools.javac.main.JavaCompiler;
|
||||
import com.sun.tools.javac.main.Main;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.Context.Factory;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Pair;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.Queue;
|
||||
import static java.util.logging.Level.FINE;
|
||||
import static java.util.logging.Level.CONFIG;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileObject;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import org.openjdk.jmh.annotations.Level;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.Setup;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.TearDown;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public class JavacBenchmark {
|
||||
|
||||
static final Logger LOG = Logger.getLogger(JavacBenchmark.class.getName());
|
||||
|
||||
public enum Stage {
|
||||
Init, Parse, InitModules, Enter, Attribute, Flow, Desugar, Generate;
|
||||
|
||||
public synchronized void waitFor() throws InterruptedException {
|
||||
wait();
|
||||
}
|
||||
public synchronized void notifyDone() {
|
||||
notifyAll();
|
||||
LOG.log(FINE, "{0} finished.", this.name());
|
||||
}
|
||||
public boolean isAfter(Stage other) {
|
||||
return ordinal() > other.ordinal();
|
||||
}
|
||||
}
|
||||
|
||||
private Path root;
|
||||
private Path srcList;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setup(Blackhole bh) throws IOException, InterruptedException {
|
||||
LOG.log(CONFIG, "Release info of the sources to be compiled by the benchmark:\n{0}", new String(JavacBenchmark.class.getResourceAsStream("/release").readAllBytes(), StandardCharsets.UTF_8));
|
||||
root = Files.createTempDirectory("JavacBenchmarkRoot");
|
||||
srcList = root.resolve("sources.list");
|
||||
int i = 0;
|
||||
try (PrintStream srcListOut = new PrintStream(srcList.toFile())) {
|
||||
try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(JavacBenchmark.class.getResourceAsStream("/src.zip")))) {
|
||||
for (ZipEntry entry; (entry = zis.getNextEntry()) != null;) {
|
||||
final String ename = entry.getName();
|
||||
if (!ename.startsWith("java.desktop") && !ename.startsWith("jdk.internal.vm.compiler") && !ename.startsWith("jdk.aot") && !ename.startsWith("jdk.accessibility") && !ename.startsWith("jdk.jsobject")) {
|
||||
if (!entry.isDirectory() && ename.endsWith(".java")) {
|
||||
Path dst = root.resolve(ename);
|
||||
Files.createDirectories(dst.getParent());
|
||||
Files.copy(zis, dst);
|
||||
Files.readAllBytes(dst); //reads all the file back to exclude antivirus scanning time from following measurements
|
||||
srcListOut.println(dst.toString());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Files.walk(root).map(Path::toFile).forEach(File::deleteOnExit); //mark all files and folders for deletion on JVM exit for cases when tearDown is not executed
|
||||
Thread.sleep(10000); //give some more time for the system to catch a breath for more precise measurement
|
||||
LOG.log(FINE, "Extracted {0} sources.", i);
|
||||
}
|
||||
|
||||
@TearDown(Level.Trial)
|
||||
public void tearDown() throws IOException {
|
||||
Files.walk(root).sorted(Comparator.reverseOrder()).map(Path::toFile).forEachOrdered(File::delete);
|
||||
LOG.fine("Sources deleted.");
|
||||
}
|
||||
|
||||
protected void compile(Blackhole bh, final Stage stopAt) throws IOException {
|
||||
final OutputStream bhos = new OutputStream() {
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
bh.consume(b);
|
||||
}
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
bh.consume(b);
|
||||
}
|
||||
};
|
||||
final Context ctx = new Context();
|
||||
//inject JavaCompiler wrapping all measured methods so they directly report to the benchmark
|
||||
ctx.put(JavaCompiler.compilerKey, (Factory<JavaCompiler>)(c) -> {
|
||||
return new JavaCompiler(c) {
|
||||
@Override
|
||||
public List<JCTree.JCCompilationUnit> parseFiles(Iterable<JavaFileObject> fileObjects) {
|
||||
Stage.Init.notifyDone();
|
||||
return stopAt.isAfter(Stage.Init) ? super.parseFiles(fileObjects) : List.nil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JCTree.JCCompilationUnit> initModules(List<JCTree.JCCompilationUnit> roots) {
|
||||
Stage.Parse.notifyDone();
|
||||
return stopAt.isAfter(Stage.Parse) ? super.initModules(roots) : List.nil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JCTree.JCCompilationUnit> enterTrees(List<JCTree.JCCompilationUnit> roots) {
|
||||
Stage.InitModules.notifyDone();
|
||||
return stopAt.isAfter(Stage.InitModules) ? super.enterTrees(roots) : List.nil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) {
|
||||
Stage.Enter.notifyDone();
|
||||
return stopAt.isAfter(Stage.Enter) ? super.attribute(envs) : new ListBuffer<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) {
|
||||
Stage.Attribute.notifyDone();
|
||||
return stopAt.isAfter(Stage.Attribute) ? super.flow(envs) : new ListBuffer<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<Pair<Env<AttrContext>, JCTree.JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) {
|
||||
Stage.Flow.notifyDone();
|
||||
return stopAt.isAfter(Stage.Flow) ? super.desugar(envs) : new ListBuffer<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(Queue<Pair<Env<AttrContext>, JCTree.JCClassDecl>> queue) {
|
||||
Stage.Desugar.notifyDone();
|
||||
if (stopAt.isAfter(Stage.Desugar)) super.generate(queue);
|
||||
}
|
||||
};
|
||||
});
|
||||
//JavaFileManager directing all writes to a Blackhole to avoid measurement fluctuations due to delayed filesystem writes
|
||||
try (JavacFileManager mngr = new JavacFileManager(ctx, true, null) {
|
||||
@Override
|
||||
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location arg0, String arg1, JavaFileObject.Kind arg2, FileObject arg3) throws IOException {
|
||||
return new ForwardingJavaFileObject<JavaFileObject>(super.getJavaFileForOutput(arg0, arg1, arg2, arg3)) {
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
return bhos;
|
||||
}
|
||||
};
|
||||
}
|
||||
}) {
|
||||
String[] cmdLine = new String[] {"-source", "25", "-XDcompilePolicy=simple", "-implicit:none", "-nowarn", "--module-source-path", root.toString(), "-d", root.toString(), "-XDignore.symbol.file=true", "@" + srcList.toString()};
|
||||
if (new Main("javac").compile(cmdLine, ctx).exitCode != 0) {
|
||||
throw new IOException("compilation failed");
|
||||
}
|
||||
}
|
||||
LOG.fine("Compilation finished.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.bench.langtools.javac;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Param;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Threads;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public class SingleJavacBenchmark extends JavacBenchmark {
|
||||
|
||||
@Param
|
||||
public Stage stopStage;
|
||||
|
||||
@Benchmark
|
||||
@Threads(1)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = 0)
|
||||
@Measurement(iterations = 1)
|
||||
@Fork(warmups = 1, value = 15, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void compileCold(Blackhole bh) throws IOException {
|
||||
compile(bh, stopStage);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@Threads(1)
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@Warmup(iterations = 8)
|
||||
@Measurement(iterations = 10)
|
||||
@Fork(warmups = 0, value = 1, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" })
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
public void compileHot(Blackhole bh) throws IOException {
|
||||
compile(bh, stopStage);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue