Java vs. C
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; /*throw new Exception("Done");*/
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.