Skip to content

Commit

Permalink
use VB.alignTo only if RHS is significantly larger
Browse files Browse the repository at this point in the history
* To cempensate for alignTo's (small, but constant) overhead, it is only
called when the right Vector is mor then 64 elemente longer than the
left one.
* replaced some `….knownSize` by `k`
  • Loading branch information
ansvonwa committed Oct 31, 2022
1 parent a30168d commit 7b8c407
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
11 changes: 7 additions & 4 deletions src/library/scala/collection/immutable/Vector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va
}

protected[this] def prependedAll0[B >: A](prefix: collection.IterableOnce[B], k: Int): Vector[B] = {
// k >= 0, k = prefix.knownSize
val tinyAppendLimit = 4 + vectorSliceCount
if (k < tinyAppendLimit /*|| k < (this.size >>> Log2ConcatFaster)*/) {
var v: Vector[B] = this
Expand All @@ -217,14 +218,15 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va
val it = this.iterator
while (it.hasNext) v = v :+ it.next()
v
} else if (prefix.knownSize >= 0 && prefix.knownSize < this.size) {
new VectorBuilder[B].alignTo(prefix.knownSize, this).addAll(prefix).addAll(this).result()
} else if (k < this.size - AlignToFaster) {
new VectorBuilder[B].alignTo(k, this).addAll(prefix).addAll(this).result()
} else super.prependedAll(prefix)
}

protected[this] def appendedAll0[B >: A](suffix: collection.IterableOnce[B], k: Int): Vector[B] = {
// k >= 0, k = suffix.knownSize
val tinyAppendLimit = 4 + vectorSliceCount
if(k > 0 && k < tinyAppendLimit) {
if (k < tinyAppendLimit) {
var v: Vector[B] = this
suffix match {
case it: Iterable[_] => it.asInstanceOf[Iterable[B]].foreach(x => v = v.appended(x))
Expand All @@ -236,7 +238,7 @@ sealed abstract class Vector[+A] private[immutable] (private[immutable] final va
val ri = this.reverseIterator
while (ri.hasNext) v = v.prepended(ri.next())
v
} else if (this.size < suffix.knownSize && suffix.isInstanceOf[Vector[_]]) {
} else if (this.size < k - AlignToFaster && suffix.isInstanceOf[Vector[_]]) {
val v = suffix.asInstanceOf[Vector[B]]
new VectorBuilder[B].alignTo(this.size, v).addAll(this).addAll(v).result()
} else new VectorBuilder[B].initFrom(this).addAll(suffix).result()
Expand Down Expand Up @@ -2000,6 +2002,7 @@ private[immutable] object VectorInline {
final val WIDTH5 = 1 << BITS5
final val LASTWIDTH = WIDTH << 1 // 1 extra bit in the last level to go up to Int.MaxValue (2^31-1) instead of 2^30:
final val Log2ConcatFaster = 5
final val AlignToFaster = 64

type Arr1 = Array[AnyRef]
type Arr2 = Array[Array[AnyRef]]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package scala.collection.immutable

import org.openjdk.jmh.annotations._
import org.openjdk.jmh.infra.Blackhole

import java.util.concurrent.TimeUnit

@BenchmarkMode(Array(Mode.AverageTime))
@Fork(1)
@Threads(1)
@Warmup(iterations = 4)
@Measurement(iterations = 5)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
class VectorConcatAlignToWorstCaseBenchmark {
@Param(Array("1", "15", "31", "33", "63", "65", "127", "255", "513", "1023", "1025", "2047")) // should not be divisible by 32
var size: Int = _
@Param(Array("1", "32", "64", "128", "256"))
var sizeDifference: Int = _

val o = new AnyRef

var shorter: Vector[String] = _
var longer: Vector[String] = _

@Setup(Level.Trial) def init(): Unit = {
shorter = Vector.fill(size)("s")
longer = Vector.fill(size + sizeDifference)("l")
}

@Benchmark def withoutAlignTo(bh: Blackhole): Any =
bh.consume(new VectorBuilder[String]().addAll(shorter).addAll(longer).result())

@Benchmark def withAlignTo(bh: Blackhole): Any =
bh.consume(new VectorBuilder[String]().alignTo(shorter.length, longer).addAll(shorter).addAll(longer).result())

@Benchmark def concat(bh: Blackhole): Any =
bh.consume(shorter ++ longer)
}

0 comments on commit 7b8c407

Please sign in to comment.