summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-08-30 08:26:17 +0200
committerGitHub <noreply@github.com>2016-08-30 08:26:17 +0200
commit5e91aa563dca2ea6b2aba2b767994c06a0fb2a61 (patch)
tree726196cb3bce957f728b56ca0e0d1aa5c5942376
parent4d3fd6d7ad08f9786f98ddb7c5fc7075dc7002e5 (diff)
parent42ae254d3ca398e884bba4e587a63362b173a75e (diff)
downloadscala-5e91aa563dca2ea6b2aba2b767994c06a0fb2a61.tar.gz
scala-5e91aa563dca2ea6b2aba2b767994c06a0fb2a61.tar.bz2
scala-5e91aa563dca2ea6b2aba2b767994c06a0fb2a61.zip
Merge pull request #5364 from retronym/topic/instanceof-perf-2
SI-9823 Collections perf: favor virtual call over instanceof
-rw-r--r--src/library/scala/collection/GenTraversableOnce.scala6
-rw-r--r--src/library/scala/collection/IndexedSeqLike.scala2
-rw-r--r--src/library/scala/collection/mutable/Builder.scala23
3 files changed, 21 insertions, 10 deletions
diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala
index 4af2ca23be..d3096a872c 100644
--- a/src/library/scala/collection/GenTraversableOnce.scala
+++ b/src/library/scala/collection/GenTraversableOnce.scala
@@ -96,6 +96,12 @@ trait GenTraversableOnce[+A] extends Any {
*/
def size: Int
+ /** The size of this $coll if it is can be cheaply computed
+ *
+ * @return the number of elements in this $coll, or -1 if the size cannot be determined cheaply
+ */
+ protected[collection] def sizeHintIfCheap: Int = -1
+
/** Tests whether the $coll is empty.
*
* Note: Implementations in subclasses that are not repeatedly traversable must take
diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala
index f4bf58ffe3..f0cede224d 100644
--- a/src/library/scala/collection/IndexedSeqLike.scala
+++ b/src/library/scala/collection/IndexedSeqLike.scala
@@ -92,4 +92,6 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] {
copyToBuffer(result)
result
}
+
+ override protected[collection] def sizeHintIfCheap: Int = size
}
diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala
index 8d6a0ec69d..528f78bd98 100644
--- a/src/library/scala/collection/mutable/Builder.scala
+++ b/src/library/scala/collection/mutable/Builder.scala
@@ -65,18 +65,18 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
/** Gives a hint that one expects the `result` of this builder
* to have the same size as the given collection, plus some delta. This will
* provide a hint only if the collection is known to have a cheap
- * `size` method. Currently this is assumed to be the case if and only if
- * the collection is of type `IndexedSeqLike`.
- * Some builder classes
- * will optimize their representation based on the hint. However,
+ * `size` method, which is determined by calling `sizeHint`.
+ *
+ * Some builder classes will optimize their representation based on the hint. However,
* builder implementations are still required to work correctly even if the hint is
* wrong, i.e. a different number of elements is added.
*
* @param coll the collection which serves as a hint for the result's size.
*/
def sizeHint(coll: TraversableLike[_, _]) {
- if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) {
- sizeHint(coll.size)
+ coll.sizeHintIfCheap match {
+ case -1 =>
+ case n => sizeHint(n)
}
}
@@ -94,8 +94,9 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
* @param delta a correction to add to the `coll.size` to produce the size hint.
*/
def sizeHint(coll: TraversableLike[_, _], delta: Int) {
- if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) {
- sizeHint(coll.size + delta)
+ coll.sizeHintIfCheap match {
+ case -1 =>
+ case n => sizeHint(n + delta)
}
}
@@ -112,8 +113,10 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
* than collection's size are reduced.
*/
def sizeHintBounded(size: Int, boundingColl: TraversableLike[_, _]) {
- if (boundingColl.isInstanceOf[collection.IndexedSeqLike[_,_]])
- sizeHint(size min boundingColl.size)
+ boundingColl.sizeHintIfCheap match {
+ case -1 =>
+ case n => sizeHint(size min n)
+ }
}
/** Creates a new builder by applying a transformation function to