Closed LuciferYang closed 2 years ago
cc @SethTisue for help ~
Looks like 2.12 has an optimized implementation of reduceLeft
for indexed seqs.
Could we migrate the relevant optimization to 2.13.x ?
I believe a PR on that would be accepted.
fyi @scala/collections
IndexedSeq
has a foldRight
that goes through the reverseIterator
view (which uses indexed access and counts down).
There is nothing comparable to the 2.12 IndexedSeqOptimized
which has "tight loops" for these operations.
I don't mind spending some time with this issue as a learning experience, but if someone better equipped has time because of a July 4 holiday, or a July 14 holiday, etc, that would be fine.
Before and after overriding reduceLeft
in ArrayBuffer
itself, I don't know why the before isn't linear in the small sizes
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 10 avgt 30 26.010 ± 1.332 ns/op
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 100 avgt 30 141.075 ± 2.798 ns/op
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 1000 avgt 30 6955.457 ± 32.765 ns/op
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 10000 avgt 30 69772.641 ± 136.585 ns/op
[info] Benchmark (size) Mode Cnt Score Error Units
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 10 avgt 30 39.154 ± 0.459 ns/op
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 100 avgt 30 420.462 ± 3.671 ns/op
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 1000 avgt 30 3971.257 ± 2.580 ns/op
[info] ArrayBufferBenchmark.min$minusmax$u0020is$u0020reduction 10000 avgt 30 39887.655 ± 176.183 ns/op
Presumably there will be smaller gains after moving the override to a trait. (30% here vs 20% in OP.)
A comment suggests at small size, it witnesses whether JIT kicked in.
immutable.ArraySeq
has overrides, or foldLeft
but not reduceLeft
. Also, ArrayBuffer
benefits an extra few % by direct array access, so it's worth it. People keep saying don't use array, use ArrayBuffer
.
Oh, the reason my local 2.13.2 scaladoc doesn't show the override in ArraySeq
is that japgolly added it during pandemic. Golly.
Reproduction steps
Scala version: 2.13.8
The test program is as follows
The
Benchmark
of spark is used to record time, which can also be changed to manual timing.In above cases, I test 2 operations:
ArrayBuffer.min
,ArrayBuffer.max
, with different buffer size: 1000, 10000, 100000.Scala 2.12.16 result:
Scala 2.13.8 result:
Problem
From the test results, Scala 2.13.8 is slower than Scala 2.12.16 for
ArrayBuffer.min
andArrayBuffer.max
. Should they have the same performance? Or should I use other data structures in Scala 2.13?