scala3
scala3 copied to clipboard
Performance concern regarding NumericRange.contains
Compiler version
3.7.0 and probably all prior
Minimized example
val m = Integer.MAX_VALUE.toLong
val n = 1000000000
val i = 2L * m - 2L
val range = m until i + 1L
val t0 = System.currentTimeMillis ; (1 to n) foreach (_ => range.start <= i && i < range.end) ; System.currentTimeMillis - t0
val t1 = System.currentTimeMillis ; (1 to n) foreach (_ => range.contains(i)) ; System.currentTimeMillis - t1
Output
val i: Long = 4294967292
val m: Int = 2147483647
val n: Int = 1000000000
val range: scala.collection.immutable.NumericRange.Exclusive[Long] = NumericRange 2147483647 until 4294967293
val t0: Long = 1748538438604
val res1: Long = 5533
val t1: Long = 1748538462486
val res3: Long = 14021
Expectation
res3 should be similar to res1, not two to three times as much.
refs: https://github.com/scala/scala3/discussions/18044
Range is an Int range. IMO there is no more reason to specialize its contains method for Longs than for Doubles or BigInts.
May I suggest to alter the call site instead?
(1 to n) foreach (_ => i.toInt == i && range.contains(i.toInt))
My bad for mentioning Range. That's not my use case, so I removed the link to Range.contains and updated the issue title.
val range: scala.collection.immutable.NumericRange.Exclusive[Long]
Here is the corresponding contains method:
https://github.com/scala/scala/blob/v2.13.16/src/library/scala/collection/immutable/NumericRange.scala#L290
Because of this inherent/essential additional cost, this might simply become an API documentation issue where we could recommend using an explicit comparison if performance is critical.