views:

95

answers:

4

I noticed that the startup time of a minimal console application in Java is slightly more than 100 ms on my machine compared to 1 ms of an equivalent C application. Although it is not a problem in most cases I would like to find out if there is a way to reduce this time because I need to write an application that will be executed many times (say in a loop within a bash script).

+2  A: 

You asking for the "Achilles' heel" of Java. There is really not much to do with it. The last Java version will be the most performant, they are working for years on that issue.

Anyway running the same program several times you will notice that after first startup the next is much more faster. I think that comes from the OS caching mechanism.

The only real way to make it better is to let run your app in background and comunicate with your app maybe thru a web service (that is what servelet container is all about).

100ms not sounds too much but could be unacceptable in your case.

PeterMmm
Unfortunately Java Quick Starter applies only to Windows.
vitaut
Indeed, the startup time improves for the later runs but 100 ms is an improved time. I was thinking of starting some kind of a background process on the first run and use it in the later runs, but not sure yet how to do this.
vitaut
You can write an app that listen on a TCP socket, receiving some commands and get back the result as plain text. Connect to the socket with netcat from your script. That's it (nearly!).
PeterMmm
Try this: http://martiansoftware.com/nailgun/index.html
PeterMmm
A: 

So here are some details about the solution I used.

Starting from this trivial program (HelloWorld.java) which took about 100ms to execute:

class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
   }
}

$ javac HelloWorld.java
$ time java HelloWorld
Hello, world!

real    0m0.109s
user    0m0.030s
sys     0m0.030s

I converted it into a trivial server:

import java.io.*;
import java.net.*;

class HelloWorldThread extends Thread {
    private Socket socket;

    public HelloWorldThread(Socket s) {
        super("HelloWorldThread");
        socket = s;
    }

    public void run() {
        try {
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            out.println("Hello, world!");
            out.close();
            socket.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class HelloWorld {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(30281);
            while (true)
                new HelloWorldThread(serverSocket.accept()).start();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

start it once and use netcat to connect to it (thanks PeterMmm for the idea) which resulted in the execution time of just 3ms:

$ javac HelloWorld.java
$ java HelloWorld &
$ time nc localhost 30281
Hello, world!

real    0m0.003s
user    0m0.000s
sys     0m0.000s
vitaut
+1  A: 

Compile your code to native code using GCJ. Will help a little, don't expect too much though.

Steve-o
+1 because it does give 2.5x speedup. However it still takes 40ms which is ~10 times slower then the netcat solution.
vitaut
A: 

And maybe java is not the best tool for the job? Using client-server approach just for performance reasons seems to me like a really bad idea. You introduce additional complexity and points of failure. What if server crashes or tcp port is already taken, etc?

Jacek Ławrynowicz
If I could use a different language I wouldn't ask this question. Java is a requirement. But you are right, there is additional complexity although I was surprised how easy it was to implement the server in Java.
vitaut
If language cannot be changed I would suggest using named pipe insted of tcp socket. It's simpler and more reliable solution.
Jacek Ławrynowicz