[Java] Java: Which is faster, streams or loops

3 minute read

I have expectations before I do it, but I think it is important to keep it in shape.

How is the processing speed of the stream?

Streams in the Java language are a feature that can be written according to the flow, and if used properly, it has the possibility of moving to code with excellent readability, that is, the one that is easy to predict behavior. It makes you feel comfortable if you can describe it in a flow that does not cause branching.

But when it comes to run-time, is it really a stream? A common possibility is to stream what you were writing in a loop.

Try it

So, let’s measure the time it takes to generate a million random numbers and add them all. The execution environment is Win10Pro (i5, 8GB RAM).

InfinitTest2_loop.java



public class InfinitTest2_loop {

public static void main(String[] args) {
Double result = 0.0;
var start = System.currentTimeMillis();
for (int i = 0; i <100 * 10000; i++) {
result += Math.random();
}
var end = System.currentTimeMillis();
System.out.println(result);
System.out.println("Duration (ms): "+ (end-start));
}
}

Let’s quickly convert this code into a stream. Let’s pass it to reduce() and describe the addition process.

InfinitTest2.java


import java.util.stream.Stream;

public class InfinitTest2 {

public static void main(String[] args) {
var start = System.currentTimeMillis();
Double result = Stream.generate(Math::random)
.limit(100 * 10000)
.reduce((p, q) -> p + q).get();
var end = System.currentTimeMillis();
System.out.println(result);
System.out.println("Duration (ms): "+ (end-start));
}
}

So I tried both. It is a millisecond when running 3 times each

  • Loop version: 45,41,39
  • Stream version: 63,71,70

The loop version runs about 70% the processing time of the stream version. Yeah, after all, the loop version that does not handle class processing poorly is faster.

“Optimization” that cannot be stupid

I must not end here, Java is Java including the execution environment. For example, when the Java VM is set to the server mode, a normal VM (Client VM) tries to optimize as much as possible before execution while being aware of the optimization being executed.

PS> java -server -cp .InfintTest
499714.1320036936
Duration (ms): 63

It doesn’t change much, but when it repeats, it stays within 65 ms, so it seems that we are trying to “optimize as much as possible”.

Another thing to talk about optimization is the problem of “optimization during execution” that came out easily, and it is a movement to “optimize the parts that are frequently executed” in sequence. In other words, if it loops, isn’t that part speeded up by optimization?

Let’s loop a lot of the above process. This part will be written using for so that no difference will occur.


public class InfinitTest2_loop {

public static void main(String[] args) {
for (int n = 0; n <100; n++) {
Double result = 0.0;
var start = System.currentTimeMillis();
for (int i = 0; i <100 * 10000; i++) {
result += Math.random();
}
var end = System.currentTimeMillis();
System.out.println(result);
System.out.println("Duration (ms): "+ (end-start));
}
}

}
import java.util.stream.Stream;

public class InfinitTest {

public static void main(String[] args) {
for (int i = 0; i <100; i++) {
var start = System.currentTimeMillis();
Double result = Stream.generate(Math::random).limit(100 * 10000).reduce((p, q) -> p + q).get();
var end = System.currentTimeMillis();
System.out.println(result);
System.out.println("Duration (ms): "+ (end-start));
}
}
}

I tried to repeat it 100 times. Whether or not optimization started in the middle, the millisecond output gradually decreased.

When I put out the last three times each, it became like this.

  • Loop version: 33,34,22
  • Stream version: 32,30,39

Oh, the difference is close (although the loop version is still fast).

So, if you have to be aware of speed when you should replace the loop processing with a stream,

  • Be aware that the speedup of the stream part can be expected to be optimized by iterative processing
  • If the loop is processed only once, it is faster to leave the loop without expecting optimization

I wonder if that is the case.

Boyaki

I wonder if there is no stream generator that generates data an infinite number of times (until some conditions are met) without passing anything. It is a story of whether while(true){...} can be expressed in a stream.