Difference between revisions of "Java vs. C"

From Simson Garfinkel
Jump to navigationJump to search
m (New page: Several people have told me recently that Java runs as fast as C. After repeating this information somewhat, I decided to test it for computer forensics. The test I constructed a test fil...)
 
m
Line 87: Line 87:
byte[] buf = new byte[4096];
byte[] buf = new byte[4096];
int count = fis.read(buf);
int count = fis.read(buf);
if(count==-1) break; /*throw new Exception("Done");*/
if(count==-1) break;  
md.update(buf);
md.update(buf);
byte[] f = md.digest();
byte[] f = md.digest();
Line 126: Line 126:
</pre>
</pre>
So those are pretty interesting numbers. Java seems to be running 3x slower.
So those are pretty interesting numbers. Java seems to be running 3x slower.
==Second Java Try==
It's possible that most of the Java overhead was in creating the new hash object each time through. So I tried this version, which makes one hash object and then clones it:

Revision as of 13:33, 28 May 2009

Several people have told me recently that Java runs as fast as C. After repeating this information somewhat, I decided to test it for computer forensics.

The test I constructed a test file of 4238912226 bytes. The test involved reading the file 4K byte blocks at a time and computing the SHA1 hash of each block.

Here is the C program I used:

#include <stdio.h>
#include <stdlib.h>
#include <openssl/sha.h>

int main(int argc,char **argv)
{
    
    FILE *f = 0;
    if(argc!=2){
	fprintf(stderr,"usage: %s - compute block hashes (but don't print them)\n");
    }
    f = fopen(argv[1],"r");
    if(!f) {
	perror(argv[1]);
	exit(1);
    }
    while(!feof(f)){
	char buf[4096];
	unsigned char md[20];
	size_t count = fread(buf,1,sizeof(buf),f);
	SHA_CTX c;
	SHA_Init(&c);
	SHA_Update(&c,buf,count);
	SHA_Final(md,&c);
    }
    fclose(f);
}

I ran the test 3 times on my Mac Pro (2x2.66 Ghz Dual-Core Intel Xeons, 12GB 667 Mhz DDR2 FB-DIMM memory, 1TB hard drive)

12:59 PM m:~/nps/speedtest$ time ./ctest /realistic.aff 

real	0m53.443s
user	0m25.459s
sys	0m6.113s
01:00 PM m:~/nps/speedtest$ time ./ctest /realistic.aff 

real	0m31.137s
user	0m25.327s
sys	0m5.650s
01:01 PM m:~/nps/speedtest$ time ./ctest /realistic.aff 

real	0m31.694s
user	0m25.392s
sys	0m5.920s
01:02 PM m:~/nps/speedtest$

The first time the file was being read off the disk, the second two trials the file was in memory.

Interestingly, the entire file can be read in around 8 seconds on this hardware:

time dd if=/realistic.aff of=/dev/null bs=4096
1034890+1 records in
1034890+1 records out
4238912226 bytes transferred in 7.786416 secs (544398372 bytes/sec)

real	0m7.979s
user	0m1.455s
sys	0m6.335s
01:22 PM m:~/nps/speedtest$ 

So how fast is Java? Here is my first Java program:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.*;
//import System.currentTimeMillis;

	
public class jtest {
    public static void main(String[] args){
	long t0 = System.currentTimeMillis();
	try {
	    System.out.println("Start");
	    FileInputStream fis = new FileInputStream(new File(args[0]));
	    while(true){
		MessageDigest md = MessageDigest.getInstance("SHA");
		byte[] buf = new byte[4096];
		int count = fis.read(buf);
		if(count==-1) break; 
		md.update(buf);
		byte[] f = md.digest();
	    }
	    System.out.println("Done");
	}
	catch (IOException e){
	    System.out.println(e);
	}
	catch (NoSuchAlgorithmException e){
	    System.out.println(e);
	}
	long t1 = System.currentTimeMillis();
	System.out.printf("Miliseconds to execute: %d\n",t1-t0);
    }
}

Notice that I have the program report how long it takes to run the benchmark, so we can factor out the cost of JVM startup.

01:14 PM m:~/nps/speedtest$ time java jtest  /realistic.aff 
Start
Done
Miliseconds to execute: 97843

real	1m39.227s
user	1m29.803s
sys	0m7.687s
01:15 PM m:~/nps/speedtest$ time java jtest  /realistic.aff 
Start
Done
Miliseconds to execute: 95853

real	1m36.944s
user	1m28.722s
sys	0m7.189s
01:18 PM m:~/nps/speedtest$ 

So those are pretty interesting numbers. Java seems to be running 3x slower.

Second Java Try

It's possible that most of the Java overhead was in creating the new hash object each time through. So I tried this version, which makes one hash object and then clones it: