简体   繁体   中英

Why does the execution of a Java program take longer than the same program in C?

So I have 2 programs that do the same things, one written in C and the other in Java. They both create 50 threads and wait for all of them to finish, then terminates.

In order to get a feel for the time difference between the 2 programs, I used the 'time' command in Linux to get the execution time.

For the C program, total execution time was 0.020 seconds, while it took the Java version 0.663 seconds to complete.

I've tried searching for an answer but all I've found were some articles such as ( these two ) saying that Java was actually faster than C, which I thought was nonsense, so I would really appreciate if anyone could clarify this for me.

Thanks.

This is what the C code looks like.

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#define N 50

void* tproc(void *arg) {
    printf("Thread %d\n", *((int *) arg));
    return NULL;
}

int main(int argc, char * argv[]) {
    int i;
    int targ[N];
    pthread_t tid[N];
    for(i = 0; i < N; i++) {
    targ[i] = i;
        if(pthread_create(&(tid[i]), NULL, &tproc, &targ[i]) != 0) {
            printf("Can't create thread %d\n", i);
            return 1;
        }
    }
    for(i = 0; i < N; i++) {
        if(pthread_join(tid[i], NULL) != 0) {
            printf("Can't join thread %d\n", i);
        }
    }
    return 0;
}

This is what the Java code looks like.

import java.util.concurrent.*;

class MyThread extends Thread {

    static final int N = 50 ;
    int arg;

    public MyThread(int arg) {
        this.arg = arg;
    }

    public void run() {
       System.out.println("Thread " + arg);
    }

    public static void main(String [] args) {
        MyThread[] tid = new MyThread [N] ;
        for(int i = N-1; i >= 0; i--) {
            tid[i] = new MyThread(i);
            tid[i].start();
        }
        for(int i = 0; i < N; i++) {
            try { tid[i].join(); }
            catch(InterruptedException e) { }
        }
    }
}

Add some profiling/time measurement to know for sure. For instance, add a timer inside your code, to measure how long does main take to run. And run the test many times, as CPU time of a process can vary a lot from execution to execution (because of whatever else the OS is doing, etc)

C programs are compiled to native machine code, closely related to assembly. That means, that the program gets compiled (pretty much) to individual instructions that the CPU already knows how to execute.

Java programs are usually compiled to intermediate bytecode, not to native machine code. The CPU won't (most likely) know how to run these instructions. Running a Java program involves starting the JVM, which will translate these bytecode instructions to native machine code, and then they will be executed by the CPU. This step of loading the JVM and translating the code takes extra time, that's outside of your 'main' function running.

Also to be taken into account is that Java has a garbage collector that, among other things, protects against resource leaks. C lacks this, which means you have to manage resources yourself. The Java garbage collector also takes time to start and may incur a CPU time overhead during execution, depending on the program.

There are other low level and high level considerations here, but this is just for starters...

Because a Java Program (actually it's the compiled binary, aka bytecode) is running on top of a virtual machine named JVM, while native binaries (eg, in your wording, C program) are running on bare metal. The JVM will do quite a little work to enable the virtual "instructions" run a bare metal, eg, interpretation as a primitive and naive implementation, JIT as a more sophisticated measure. Besides, the automatic memory management mechanism named garbage collection (GC) will slow down the virtual machine significantly when your application is memory allocation intensive. If you are interested in the JVM specification, please learn more from https://docs.oracle.com/javase/specs/jvms/se7/html/

Another possible reason is that when you launch java you need to load all the runtime into memory.

Maybe try instrumenting your code to measure the actual running time of the code and not that of the execution of the whole command and you might see different results.

It is likely C will still be faster as Java bytecode is interpreted at the beginning. However, with very long loops, at some time, the just-in-time (JIT) compiler might kick in and probably performance may become similar to that of a compiled language.

Other reason Java can sometimes be faster than C: in programs with dynamic allocation of lots of data structures, Java's garbage collector will usually collect whole batches of objects together, thus optimizing the time needed to free memory. On the other hand, in C, you have to call free manually, destructing one object at a time. This is both a good thing since you control when it happens, and a bad thing since the kind of optimization I mentioned is had to come up with (also automatic garbage collection is good because it will prevent many memory leaks anyway).

Several reasons:

  1. Compiled C code (typically) runs natively, whereas compiled Java code (typically) runs in a virtual machine (basically a machine-code-level interpreter) - all things being equal, native code will run faster than code in a VM;

  2. Compiled Java code performs a number of run-time checks that compiled C code does not (array bounds checks, null pointer checks, etc);

  3. The Java virtual machine performs periodic garbage collection of heap-allocated objects that are no longer being used - C doesn't do any kind of automated memory management at all;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM