2

Is there a way to execute a command in java that doesn't suffer from the startup overhead (slowness) of using ProcessBuilder?

More detail: I am using im4java which is a java library that internally uses ProcessBuilder to execute imagemagick's programs. It is slow. I have created a small unit test that shows that ProcessBuilder (not im4java) is the problem. The slowness is the startup overhead of using ProcessBuilder. I have found posts around the internet saying processbuider has overhead so its not just me saying it does.

List<String> commands = new ArrayList<String>();
commands.add("C:\\PROGRA~2\\ImageMagick-6.6.4-Q16\\convert.exe");
commands.add("dog.jpg");
commands.add("output.jpg");
ProcessBuilder processBuilder = new ProcessBuilder(commands);
Process start = processBuilder.start();
start.waitFor();
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Plaudit Design
  • 1,156
  • 8
  • 16
  • 1
    Is performance _really_ an issue, or just 'annoying' during testing? Using ProcessBuilder is encouraged over say using Runtime.exec() for several good reasons (http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html). – Martijn Verburg Oct 15 '10 at 15:10
  • Yes performance is an issue. I was wrong though on how much time ProcessBuilder degrades the performance. It doesn't add too much. There just seems to be slow downs in a few places so it is adding up. – Plaudit Design Oct 19 '10 at 15:39

2 Answers2

0
Runtime.getRuntime().exec(...)  

can be used to run an external command. You can turn your List into a command array or a string to pass to exec().

robert_x44
  • 9,224
  • 1
  • 32
  • 37
  • Thanks but I have done that too. It seems to have the same overhead. Do you know different? (my test case could just be misleading) – Plaudit Design Oct 15 '10 at 15:11
  • Nope. as another commenter noted, you are already using the preferred method of executing another application. If this isn't faster, there is probably not much you can do. – robert_x44 Oct 15 '10 at 15:14
  • `Runtime.getRuntime().exec()` uses `ProcessBuilder`. – Jonathan Oct 18 '10 at 13:07
0

This is not recommended, but you could write a JNI library to do the same thing that ProcessBuilder is doing. Perhaps yours would be faster, but I wouldn't count on it, plus you would lose cross-platform compatibility.

How slow are we talking here? I'm using ProcessBuilder myself for running Git commands (haven't had a chance to look into JGit yet), and it seems snappy enough. You may have better luck on Linux, as the overhead may actually be in Windows heavyweight process creation.

Jonathan
  • 13,354
  • 4
  • 36
  • 32
  • One second in Windows and two seconds in linux. (The windows machine is much better hardware then the linux machine) When I run the program directly (not form java) it runs in milliseconds. – Plaudit Design Oct 17 '10 at 18:17
  • I just looked at the `ProcessBuilder` and `Runtime.exec()` code. `Runtime.exec()` uses `ProcessBuilder`, and the only likely slowdown in `ProcessBuilder` is converting a list to an array of strings, and then copying that array. If you really need more speed, you'll likely need to write your own native implementation. – Jonathan Oct 18 '10 at 13:06