Class files compiled by this extention run faster than manually compiled with javac command.
See original GitHub issueI was about to benchmark this program.
public class App {
public static void main(String[] args) {
int n_iters = Integer.parseInt(args[0]);
long tInit = System.currentTimeMillis();
int c = 0;
for (int i = 0; i < n_iters; ++i) {
for (int j = 0; j < n_iters; ++j) {
for (int k = 0; k < n_iters; ++k) {
if (i * i + j * j == k * k) {
++c;
}
}
}
}
System.out.println(c);
System.out.println((System.currentTimeMillis() - tInit) / 1000.0);
}
}
I found the class file compiled by VSCode Java extention runs about 4 times faster than one I compiled manually by the javac
command.
Environment
- Operating System: Windows 11 /Debian 11
- JDK version: java 17.0.3.1
- Visual Studio Code version: 1.71.2
- Java extension version: v1.11.0
Steps To Reproduce
- clone git@github.com:lucidfrontier45/java_bench.git
- open the cloned directory with VSCode
- confirm VSCode has compiled
bin/App.class
- manually compile
src/App.java
tosrc/App.class
byjavac src/App.java
. - run manually compiled one
java -cp src App 1000
- run VSCode compiled one
java -cp bin App 1000
- confirm 6 is faster than 5.
[Please attach a sample project reproducing the error] https://github.com/lucidfrontier45/java_bench
Current Result
PS C:\Users\lucid\workspace\java_bench> java -cp src App 1000
3755
1.946 sec
PS C:\Users\lucid\workspace\java_bench> java -cp bin App 1000
3755
0.564 sec
Expected Result
Both of them end in almost same duration.
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:6
Top Results From Across the Web
terminal not overwriting .class files - java - Stack Overflow
for the class i have to use jEdit to write programs, and terminal to compile and run them (i have a mac, and...
Read more >Compiling Java *.class Files with javac - Baeldung
This tutorial will introduce the javac tool and describes how to use it to compile Java source files into class files.
Read more >Chapter 1. Getting Started: Compiling and Running Java
Use the commands javac to compile and java to run your program (and, ... and a compiled .class file is not, javac will...
Read more >The javac Command - Oracle Help Center
The javac command reads source files that contain module, package and type declarations written in the Java programming language, and compiles them into...
Read more >Javac Task - Apache Ant
The source and destination directory will be recursively scanned for Java source files to compile. Only .java files that have no corresponding .class...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Hi, this is how Java usually works, it interprets the code and if something is run multiple times, the VM asks the JIT to generate the corresponding assembly code and jump on it.
For Hotspot (the default OpenJDK VM), that optimization occurs either when a method is called several times (in the thousand) or a loop is called several times. The later optimization is called on stack replacement optimization.
Loop optimizations is a vast subject, but depending on the kind of loops, the JITs optimize them differently. I believe that the question here is, does the JIT is able to prove that the loop will finish fast enough so there is no need to insert a check to maybe trigger the GC when the loop run. If the JIT does not know, it has to insert such check (named a safepoint check).
For that, the JIT will try to prove that the loop finish, here, each loop is bounded and iterate over an int, usually it’s enough for the JIT to consider that the loop will finish soon enough.
It seems that depending on the bytecode generated either, the JIT struggles to detect the kind of loops or there is a bad interaction between the loop detection and the on stack replacement mechanism, but clearly there is a bug somewhere.
I suggest you to report that as a bug of the hotspot compiler (the JIT).
@tivrfoa @fbricon
The benchmark program I posted was taken from https://stackoverflow.com/questions/67211077/java-vs-rust-performance .
Since this program is mostly composed by primitive variables without any complex memory allocation, I expected it to be as fast as C or Rust. In fact, the class file compiled with ecj runs as fast as C and Rust. I’m not sure why javac cannot do this.
There is an explanation (though I couldn’t understand.)
https://stackoverflow.com/questions/73814988/why-is-java-program-compiled-by-vscode-faster-than-one-created-by-manually-runni#comment130342732_73814988
I also found that in the triple ijk loop, if I extract jk loop as an function, the JVM JIT can optimize it and it runs faster, close to C and Rust.