RockManX77777
RockManX77777

Reputation: 171

Java ProcessBuilder.start() taking considerably longer than executing in a terminal

I have a GUI that starts a new thread (getFilesThread) when the user clicks a button. This thread invokes the start() method of an instance of my ClearCaseProcess class below (my organization won't let me use the ClearCase Java API), and when the process(es) ends, it updates the GUI.

private static class ClearCaseProcess {

private ArrayList<String> stdout = new ArrayList<>();
private ArrayList<String> stderr = new ArrayList<>();
private ProcessBuilder pb = null;

public ClearCaseProcess(ArrayList<String> commands, String dir) throws IOException {
    pb = new ProcessBuilder(commands);
    pb.directory(new File(dir));
}

public void start() throws IOException {
    long minStart = System.nanoTime();

    Process process = pb.start();

    Thread sout = new Thread() {
        @Override
        public void run() {
            BufferedReader out = new BufferedReader(
                new InputStreamReader(process.getInputStream()));

            String outLine = "";

            try {
                while ((outLine = out.readLine()) != null) {
                    stdout.add(outLine);
                    System.out.println(outLine);
                }
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }
        }

    };
    sout.start();

    Thread serr = new Thread() {
        @Override
        public void run() {
            BufferedReader err = new BufferedReader(
                new InputStreamReader(process.getErrorStream()));

            String errLine = "";

            try {
                while ((errLine = err.readLine()) != null) {
                    stderr.add(errLine);
                    System.err.println(errLine);
                }
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }
        }
    };
    serr.start();

    try {
        process.waitFor();
        long execTime = System.nanoTime() - minStart;
        System.out.println("Process '" + description + "' took " + execTime);
    } catch (InterruptedException ex) {
        System.err.println(ex.getMessage());
    }
}

}

getFiles() needs to gather data from four different ClearCaseProcesses. I plan to run these concurrently in four threads. Each of these threads has two associated auxiliary threads to consume stdout and stderr, as shown above. I'm assuming that this will be faster than running ClearCase four times sequentially. For now, however, I'm testing just one ClearCase call.

My issue is that the time elapsed between calling Process.start() and the return of Process.waitFor() is much longer (about 5 minutes) than the time elapsed when I run the same ClearCase command on the terminal (about 1.5 minutes). I suspect that my loops reading stdout and stderr are the culprits, because even my print statements are slow to produce output in NetBeans' console. How can I speed this up?

Upvotes: 4

Views: 1194

Answers (1)

RockManX77777
RockManX77777

Reputation: 171

For my specific case, running (not debugging) inside the IDE was causing the overhead.

When ran from the console (java -jar myExecutable.jar), the times were very close.
Noobish mistake.

Upvotes: 2

Related Questions