Skip to content

Commit d6569d3

Browse files
committed
Improve performance of generic tuples code generation
Improves the state of scala#6524. Instead of convering all tuples to arrays and performing the operations on them, we take advantage of the fact that those Tuples are products and have productIterators. Implementations of tail, *: and ++ on iterators do not require extra collentions to be created, hence it is also probably more performant at runtime.
1 parent e81fa4a commit d6569d3

File tree

1 file changed

+32
-32
lines changed

1 file changed

+32
-32
lines changed

library/src-3.x/scala/Tuple.scala

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ sealed trait Tuple extends Any {
4949
val t = asInstanceOf[Tuple4[_, _, _, _]]
5050
Tuple5(x, t._1, t._2, t._3, t._4).asInstanceOf[Result]
5151
case Some(n) =>
52-
knownTupleFromArray[H *: this.type](DynamicTuple.cons$Array(x, toArray))
52+
knownTupleFromItrator[H *: this.type](Iterator.single(x) ++ this.asInstanceOf[Product].productIterator)
5353
case _ =>
5454
DynamicTuple.dynamic_*:[This, H](this, x)
5555
}
@@ -74,7 +74,7 @@ sealed trait Tuple extends Any {
7474
val u = that.asInstanceOf[Tuple2[_, _]]
7575
Tuple4(t._1, t._2, u._1, u._2).asInstanceOf[Result]
7676
case _ =>
77-
knownTupleFromArray[Result](this.toArray ++ that.toArray)
77+
knownTupleFromItrator[Result](this.asInstanceOf[Product].productIterator ++ that.asInstanceOf[Product].productIterator)
7878
}
7979
case Some(3) =>
8080
val t = asInstanceOf[Tuple3[_, _, _]]
@@ -84,11 +84,11 @@ sealed trait Tuple extends Any {
8484
val u = that.asInstanceOf[Tuple1[_]]
8585
Tuple4(t._1, t._2, t._3, u._1).asInstanceOf[Result]
8686
case _ =>
87-
knownTupleFromArray[Result](this.toArray ++ that.toArray)
88-
}
87+
knownTupleFromItrator[Result](this.asInstanceOf[Product].productIterator ++ that.asInstanceOf[Product].productIterator)
88+
}
8989
case Some(_) =>
9090
if (constValue[BoundedSize[that.type]] == 0) this.asInstanceOf[Result]
91-
else knownTupleFromArray[Result](this.toArray ++ that.toArray)
91+
else knownTupleFromItrator[Result](this.asInstanceOf[Product].productIterator ++ that.asInstanceOf[Product].productIterator)
9292
case None =>
9393
DynamicTuple.dynamic_++[This, that.type](this, that)
9494
}
@@ -143,34 +143,32 @@ object Tuple {
143143

144144
private[scala] type BoundedSize[X] = BoundedSizeRecur[X, 23]
145145

146-
private[scala] val $emptyArray = Array[Object]()
147-
148-
private[scala] inline def knownTupleFromArray[T <: Tuple](xs: Array[Object]): T =
146+
private[scala] inline def knownTupleFromItrator[T <: Tuple](it: Iterator[Any]): T =
149147
inline constValue[BoundedSize[T]] match {
150148
case 0 => ().asInstanceOf[T]
151-
case 1 => Tuple1(xs(0)).asInstanceOf[T]
152-
case 2 => Tuple2(xs(0), xs(1)).asInstanceOf[T]
153-
case 3 => Tuple3(xs(0), xs(1), xs(2)).asInstanceOf[T]
154-
case 4 => Tuple4(xs(0), xs(1), xs(2), xs(3)).asInstanceOf[T]
155-
case 5 => Tuple5(xs(0), xs(1), xs(2), xs(3), xs(4)).asInstanceOf[T]
156-
case 6 => Tuple6(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5)).asInstanceOf[T]
157-
case 7 => Tuple7(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6)).asInstanceOf[T]
158-
case 8 => Tuple8(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7)).asInstanceOf[T]
159-
case 9 => Tuple9(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8)).asInstanceOf[T]
160-
case 10 => Tuple10(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9)).asInstanceOf[T]
161-
case 11 => Tuple11(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10)).asInstanceOf[T]
162-
case 12 => Tuple12(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11)).asInstanceOf[T]
163-
case 13 => Tuple13(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12)).asInstanceOf[T]
164-
case 14 => Tuple14(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13)).asInstanceOf[T]
165-
case 15 => Tuple15(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14)).asInstanceOf[T]
166-
case 16 => Tuple16(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15)).asInstanceOf[T]
167-
case 17 => Tuple17(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16)).asInstanceOf[T]
168-
case 18 => Tuple18(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17)).asInstanceOf[T]
169-
case 19 => Tuple19(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18)).asInstanceOf[T]
170-
case 20 => Tuple20(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19)).asInstanceOf[T]
171-
case 21 => Tuple21(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19), xs(20)).asInstanceOf[T]
172-
case 22 => Tuple22(xs(0), xs(1), xs(2), xs(3), xs(4), xs(5), xs(6), xs(7), xs(8), xs(9), xs(10), xs(11), xs(12), xs(13), xs(14), xs(15), xs(16), xs(17), xs(18), xs(19), xs(20), xs(21)).asInstanceOf[T]
173-
case _ => TupleXXL(xs).asInstanceOf[T]
149+
case 1 => Tuple1(it.next()).asInstanceOf[T]
150+
case 2 => Tuple2(it.next(), it.next()).asInstanceOf[T]
151+
case 3 => Tuple3(it.next(), it.next(), it.next()).asInstanceOf[T]
152+
case 4 => Tuple4(it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
153+
case 5 => Tuple5(it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
154+
case 6 => Tuple6(it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
155+
case 7 => Tuple7(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
156+
case 8 => Tuple8(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
157+
case 9 => Tuple9(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
158+
case 10 => Tuple10(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
159+
case 11 => Tuple11(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
160+
case 12 => Tuple12(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
161+
case 13 => Tuple13(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
162+
case 14 => Tuple14(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
163+
case 15 => Tuple15(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
164+
case 16 => Tuple16(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
165+
case 17 => Tuple17(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
166+
case 18 => Tuple18(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
167+
case 19 => Tuple19(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
168+
case 20 => Tuple20(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
169+
case 21 => Tuple21(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
170+
case 22 => Tuple22(it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next(), it.next()).asInstanceOf[T]
171+
case _ => TupleXXL(it.asInstanceOf[Iterator[Object]].toArray).asInstanceOf[T]
174172
}
175173

176174
def fromArray[T](xs: Array[T]): Tuple = {
@@ -233,7 +231,9 @@ sealed trait NonEmptyTuple extends Tuple {
233231
val t = asInstanceOf[Tuple5[_, _, _, _, _]]
234232
Tuple4(t._2, t._3, t._4, t._5).asInstanceOf[Result]
235233
case Some(n) if n > 5 =>
236-
knownTupleFromArray[Result](toArray.tail)
234+
val it = this.asInstanceOf[Product].productIterator
235+
it.next()
236+
knownTupleFromItrator[Result](it)
237237
case None =>
238238
DynamicTuple.dynamicTail[This](this)
239239
}

0 commit comments

Comments
 (0)