'How to improve performance of Java Process?
Hello stackoverflow community, I try to run a command on the console and read the input stream of this process:
String command[] = {"ffmpeg"}; //minimal command example
Process proc = processBuilder.command(command).start();
byte[] bytes = IOUtils.toByteArray(proc.getInputStream());
proc.waitFor();
The command is a very long ffmpeg command, which prints bytes to the output. Everything works just fine, but it is very slow using java. When I run this command on my regular command line tool, it takes round about 20ms, everything is printed and done. For the Java process is takes more than 2s. I also tried to redirect all I/O streams to the std, but the performance is the same, since I thought my reading is too slow. Also, reading the stream in additional threads or using other stream readers etc. did not change anything. The only thing which has an effect is adding cmd (currently working with Windows 10) to the command:
String command[] = {"cmd","/C","ffmpeg"};
resulting in a execution time of round about 400ms. I did not know before that this makes a difference, but it really does.
Since this is a Spring Boot web application and the command is used to output images from a video, 400ms is still a lot. The issue here is, that the frontend/browser requests a bunch of images (lets say 36). Apparently the simultaneous requests of a browser to one host is limited (chrome 6 requests), see here. Therefore it takes at best 6 x 400ms to deliver the content. So is there a way to improve the performance to the java process or maybe keep it open and fire commands to avoid overhead?
Solution 1:[1]
Here is the pseudo code to your question in the comments above:
ByteArrayOutputStream out = new ByteArrayOutputStream();
ProcessBuilder pb = new ProcessBuilder(command);
// Consuming STDOUT and STDERR in same thread can lead to the process freezing if it writes large amounts.
pb.redirectErrorStream(true);
Process process = pb.start();
try (var infoStream = process.getInputStream()) {
infoStream.transferTo(out);
}
status = process.waitFor();
if (status > 0)
// errorhandling
#transferTo(out) Consumes the output stream inside the processbuilder thread. That's it! It runs inside the thread of process.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Thilo Schwarz |
