-3

I have lately been curious about the relative speed of Java vs. C. Since Java is ultimately "interpreted" I'd be surprised if it turned out to be faster than C.

I wrote the following short program that checks a million times whether a number is prime. Here it is in Java:

import java.lang.Math;

class time_test {
    public static void main(String[] args){
        
        boolean prime = true;
        long start, end;
        
        try{
            // get the int
            int num = Integer.parseInt(args[0]);
            
            // start the clock
            start = System.nanoTime();
            
            for (int h=0; h<1000000; h++)
                for (int i=2; i<Math.floor(Math.sqrt(num))+1; i++)
                    if (num % i == 0) prime = false;
                
            end = System.nanoTime();
            System.out.println((end-start)/1000000000.0);
            System.out.println(prime);
            
        }
        catch(Exception e) {
            System.out.println(e.toString());
        }
    }
}

And here it is in C:

#include <time.h>
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>

clock_t start, end;

int main(int argc, char * argv[]){
    
    bool prime = true;
    int num = atoi(argv[1]);
    
    start = clock();
    for (int h=0; h<1000000; h++)
        for (int i=2; i<floor(sqrt(num))+1; i++)
            if (num%i == 0) prime = false;
        
    end=clock();
    printf("%f\n", (double) (end-start)/CLOCKS_PER_SEC);
    
    if (prime) printf("true\n");
    else printf("false\n");
}

I compiled the Java version with:

javac time_test.java

And the C version with:

gcc time_test.c -lm

However, when I ran them both with 27221 the Java version finished in 0.365623241 seconds and the C in 0.647930. How can this be? Even with -O3 optimization the C version can only do it in 0.366007 seconds, which about the same as the Java! Have I been lied to all my life? :)

Isaac D. Cohen
  • 797
  • 2
  • 10
  • 26
  • 1
    Looks like too small a sample to be significant. – Federico klez Culloca Nov 15 '22 at 15:30
  • 1
    Java bytecode runs in a virtual machine, but that's not well characterized as "ultimately interpreted". Especially not when typical VMs perform selective just-in-time compilation to native code, and some Java compilers compile directly to native code instead of to bytecode. – John Bollinger Nov 15 '22 at 15:32
  • Also, benchmarking is hard to do properly. – John Bollinger Nov 15 '22 at 15:34
  • "Have I been lied to all my life?" What lie are you referring to? – Andy Turner Nov 15 '22 at 15:34
  • 3
    "Benchmarking" C code with optimizations disabled is like measuring which car that's fastest without starting the engines... – Lundin Nov 15 '22 at 15:36
  • You are performing your C compilation without optimization enabled. It is worse than pointless to perform benchmarking on the result. Add `-O2` or `-O3` to your C compilation command. – John Bollinger Nov 15 '22 at 15:37
  • Also, without optimization enabled, GCC isn't going to hoist that `floor(sqrt())` out of the loop condition!! So that's a performance disaster. Oh, you did try with `-O3`. – Peter Cordes Nov 15 '22 at 15:45
  • The Java test is also flawed. Benchmarking a JIT application like Java or .NET is very difficult. See [How do I write a correct micro-benchmark in Java?](https://stackoverflow.com/q/504103/995714) – phuclv Nov 16 '22 at 01:03

1 Answers1

1

In the BeginningTM is was true that Java was interpreted. But these times are long gone. Today common JREs use a technique called just-in-time compilation, which translates the byte code into the native machine language of the host processor. There are even Java compilers producing native machine code.

Therefore, benchmarks show commonly comparable results for C and Java. But as writing benchmarks is really hard, your results are correct only for your specific programs. You cannot derive any statement about the power of the languages.

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • 1
    "your results are correct only for your specific programs". Well, realistically, these Java results as given are probably not correct for any real-world program. The test is too short, and doesn't account for warmup effects of the JVM. – Michael Nov 15 '22 at 15:35
  • @Michael That's why I wrote "_specific_". If the OP wants to compare the implementations of the shown algorithm, the results are correct for the specific setup, but for nothing else. Did you read any more from my words? – the busybee Nov 15 '22 at 15:42
  • Well, I'm chilled. ;-) Comments commonly ask for enhancements, so please give me a hint. – the busybee Nov 15 '22 at 15:47