-1

I run analysis on a file directly from an analyzer program and it finishes under one minute. But if I make jar of analyzer and run it via ProcessBuilder, it does not get finished even in 8 minutes (500 sec). Here is the code I am using for ProcessBuilder. Can someone please explain the reason?

I cannot run the analyzer program directly because depending upon the input file, it may actually take 15-20 minutes which I don't want. I want to finish it under 8 minutes.

Here is code for ProcessBuilder.

public void myFun(){

    String fileName = file.getName();
    System.out.println(file.getAbsolutePath());

    Process p;
    ProcessBuilder pb;
    String filePath = file.getAbsolutePath();

        pb = new ProcessBuilder("C:\\Program Files\\Java\\jdk1.7.0_13\\bin\\java.exe", "-jar", "ta.jar", filePath);
        pb.directory(new File("D:\\Softwares\\analyzerRun\\bin"));

        long startTime = System.currentTimeMillis();

        try {
            p = pb.start();
            long currTime = System.currentTimeMillis();
            long diff = currTime - startTime;

            boolean isBreak = false;
            while(diff < 500000)
            {
                currTime = System.currentTimeMillis();
                diff = currTime - startTime;

                if(processIsTerminated(p))
                {
                    isBreak = true;
                    break;
                }
            }
            if(!isBreak)
            {
                System.out.println("Interrupting current thread!!");
                p.destroy();
                Thread.currentThread().interrupt();
            }
            else
            {
                System.out.println("process terminated peacefully");
            }
            System.out.println("Done with "+ fileName);
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

private static boolean processIsTerminated (Process process) {
    try {
        process.exitValue();
    } catch (IllegalThreadStateException itse) {
        return false;
    }
    return true;
}

Edit1:

So after given suggestions, I removed while loop and my try code looks like below now:

try {
    p = pb.start();
    p.waitFor();
}

Interestingly, I run this program and it does not get finished under 5 minutes. But if I run my analyzer directly, it gets finished under 30 seconds. Does ProcessBuilder not get enough priority from CPU?

Junaid
  • 1,668
  • 7
  • 30
  • 51
  • Well, the `while` loop is going to help, as it is consuming CPU cycles, would be simpler to use `Process#waitFor` instead. – MadProgrammer Jun 02 '14 at 01:32
  • I tried that earlier but that does not get terminated forcefully (after 8 minutes) – Junaid Jun 02 '14 at 01:34
  • Then use `Thread.sleep` – MadProgrammer Jun 02 '14 at 01:43
  • Making Thread.sleep(800000) either before or after does not help. If u make it before waitFor(), does not serve the process. waitFor() is a blocking call, I think. Thread.sleep() does not help after waitFor() also. – Junaid Jun 02 '14 at 01:54
  • Sorry, use `Thread.sleep` instead of `waitFor` ;) – MadProgrammer Jun 02 '14 at 01:55
  • But it makes sure that even if process is finished before the deadline, thread will run for the specified time. right? – Junaid Jun 02 '14 at 02:07
  • Yep. In that case, you could run the process in a second `Thread` and use `waitFor` and use `Thread.sleep` in the current `Thread`, depending on who finishes first, you would simply interrupt the other thread. – MadProgrammer Jun 02 '14 at 02:08

3 Answers3

1

Your polling loop is insane.

Suggestion:

1) start() your process

2) Save the start time.

3) Call waitFor() to block until the process is done.

4) Then take the delta.

You'll get MUCH better results - honest!

If you absolutely must run asynchronously (if your app cannot block while your subprocess runs), then create a new Java thread for steps 1) ... 4).

IMHO...

ALSO: Run Windows Performance Monitor (or equivalent for your OS) and monitor I/O wait, CPU utilization, etc while the process is running to try to figure out where the latency might be coming from.

But your polling loop is itself introducing excessive CPU utilization. Don't do it!

FoggyDay
  • 11,962
  • 4
  • 34
  • 48
0

Because you're wasting most of the time smoking the CPU with sleep-free polling, instead of:

(a) consuming the process's output and error streams, and then
(b) calling waitFor().

user207421
  • 305,947
  • 44
  • 307
  • 483
0

To answer this, "Interestingly, I run this program and it does not get finished under 5 minutes. But if I run my analyzer directly, it gets finished under 30 seconds. Does ProcessBuilder not get enough priority from CPU? "

After a long-time, I finally figured out that I was writing two lines on standard output in my original program. So, when I ran the jar file using ProcessBuilder, I didn't read from standard output. The process was getting hanged ultimately getting killed by the main-class thread. I just removed those two lines from the original program and now it takes equal time in both ways.

Junaid
  • 1,668
  • 7
  • 30
  • 51
  • what was the two lines ? – shareef Jan 26 '18 at 18:27
  • @shareef I presume a usual log in SYSOUT or SYSERR. It doesn't matter. What one needs to take care of, is that you need to consume the SYSOUT and SYSERR streams or else the child process will wait until you do so (or unless killed by parent) – gmich Jun 09 '22 at 11:14