2

To my understanding streams are faster than conventional old programing.

However, when I ran following code the result is something I did not expect.

public class Application {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        int[] a = { 1, 2, 3, 4 };
        int m = Arrays.stream(a).reduce(Integer.MIN_VALUE, Math::max);
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);

    }
}

Output is :22857304

public class Application {
        public static void main(String[] args) {
        long startTime = System.nanoTime();
        int[] a = { 1, 2, 3, 4 };
        int e = a.length;
        int m = Integer.MIN_VALUE;
        for (int i = 0; i < e; i++)
            if (a[i] > m)
                m = a[i];
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        System.out.println(totalTime);
    }
}

Output is :1459

Please help me understand why is stream so slow ?

AyamDobhal
  • 33
  • 7
T-Bag
  • 10,916
  • 3
  • 54
  • 118
  • 1. Did you mean something similar as `int m = Arrays.stream(a).max().getAsInt();`. 2. Would be great to benchmark it with JMH. 3. Are you [comparing `System.nanoTime()` between threads?](https://stackoverflow.com/a/9314616/1746118) – Naman Jun 14 '19 at 10:50
  • nanoTime() do not measure accurately. Please use JMH Benchmark. – Turac Jun 14 '19 at 10:53
  • More info [here](https://stackoverflow.com/questions/34632008/key-indicators-that-a-java-8-stream-will-run-slower-than-a-for-loop) – Federico klez Culloca Jun 14 '19 at 10:54
  • 3
    @Turan `JMH` uses `System::nanoTime` under the hood too, it's not about that – Eugene Jun 14 '19 at 10:54

2 Answers2

6

explaining this entirely would take a lot of time; but what you are testing here is the "cold" start, basically without much JIT and a simple loop is not allocating Objects like a Stream solution - thus a lot less time. Streams have an infrastructure to run on - that takes a while to "heat" up to become more performant.

Those portions of the code are not equivalent either, as in one you are using Math::max, in the one one a plain >. You could test this code iterating a lot more and see the results, but even so you should probably use a tool that is tailored for micro-benchmarks, I know about JMH (and Caliper from google - but I trust only the first one).

With JMH you could test these methods with no JIT at all, C1 or C2 compiler only, or some other settings, for an example of some set-ups see this answer

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 2
    Before the JIT kicks in, the `Stream` implementation classes and the `LambdaMetaFactory` have to be loaded, verified, and initialized. That’s even more initial overhead added to the stream variant of the question. – Holger Jun 14 '19 at 11:15
0

The good old loop over primitive type such as int[] are faster because you have direct access to an indexed memory structure. Also compilers are very efficient in optimizing these operations.

Streams implementation depend on Data Structures such as List, ArrayList, which then requires the use of iterators and don't forget the boxing & unboxing to & from primitive types <-> Object.

If you run your test not using int[] but ArrayList, you might get a closer result.

In addition you can take advantage of streams parallize, for improved performance. (Depending on your cores)

Arrays.stream(ints).parallel()

A good comparison and explanation can be found here : https://jaxenter.com/java-performance-tutorial-how-fast-are-the-java-8-streams-118830.html

ehanoc
  • 2,187
  • 18
  • 23
  • Streams are "JITTED" quite effective too, it's just that there is not enough iterations for it to kick in + parallel it's not about the cores as much as about the amount of data – Eugene Jun 14 '19 at 10:57
  • 1
    A stream over an `ArrayList` will also stream over a plain array, internally. But since the OP did not even use a `List`, but just streams over an `int[]` array, no `List` and no boxing is involved. – Holger Jun 14 '19 at 11:05
  • Check the in-depth study in the link. Don't think that is correct – ehanoc Jun 14 '19 at 11:08
  • 2
    Just because that article uses `ArrayList`, doesn’t make the OP’s code use `ArrayList`. So anything said there about `ArrayList` still does not apply to the OP’s case where no `ArrayList` is involved. – Holger Jun 14 '19 at 11:12