I added some setup to make inlining the sequence lambdas more difficult:
val random = Random()
generateSequence { random.nextInt() }
.take(5_000)
.filter { it != 0}
.map { it * 2 }
.filter { it > Integer.MIN_VALUE }
.map { it xor random.nextInt()}
.count { it % 2 == 0 }
The results:
Benchmark (N) Mode Cnt Score Error Units
FilterMapLoopHelper.loopListsOnce 100000 avgt 10 1.677 ± 0.055 ms/op
FilterMapLoopHelper.loopListsTwice 100000 avgt 10 2.592 ± 0.022 ms/op
FilterMapLoopHelper.loopOptimalOnce 100000 avgt 10 1.012 ± 0.048 ms/op
FilterMapLoopHelper.loopOptimalTwice 100000 avgt 10 1.105 ± 0.058 ms/op
FilterMapLoopHelper.loopSequencesOnce 100000 avgt 10 2.339 ± 0.164 ms/op
FilterMapLoopHelper.loopSequencesOnceJava 100000 avgt 10 2.681 ± 0.215 ms/op
FilterMapLoopHelper.loopSequencesTwice 100000 avgt 10 3.394 ± 0.225 ms/op
FilterMapLoopHelper.loopSequencesTwiceJava 100000 avgt 10 3.396 ± 0.282 ms/op
That should settle things. loopOptimalOnce
was over twice as fast as loopSequencesOnce
, and loopOptimalTwice
was over three times as fast as loopSequencesTwice
. More interestingly, loopLists
is significantly less performant than loopSequences
in both cases, despite the fact that the IDE will suggest replacing inlined list operations with sequence operations.
(Writing the sequence code directly in Java didn’t appear to have an impact.)