Вот мой тестовый код:
def bm(duration: Long)(f: => Unit)={
val end = System.currentTimeMillis + duration
var count = 0
while(System.currentTimeMillis < end) { f; count += 1 }
count
}
val array = new scala.util.Random().alphanumeric.take(1000).toArray
(1 to 20).map { _ => bm(1000) { array.slice(100,200) } }.sum / 20
Выполняя это несколько раз, я последовательно получаю числа в шале около 1,5 млн. ломтиков в секунду. Между 1.4 и 1.6.
Теперь я делаю это:
implicit class FastSlicing(val a: Array[Char]) extends AnyVal {
def fastSlice(from: Int, until: Int) = Arrays.copyOfRange(a, from, until)
}
(1 to 20).map { _ => bm(1000) { array.fastSlice(100,200) } }.sum / 20
И результат, который я получаю, составляет от 16 до 18 миллионов секций в секунду. Это более 10 раз быстрее.
Теперь я знаю все обычные рассуждения о компромиссах, которые scala делает для обеспечения функциональных идиом и безопасности типов иногда за счет производительности...
Но в этом случае я думаю, что все они не могут ответить на простой вопрос: почему ArrayOps.slice
не реализован таким образом??? Я понимаю, было бы много одинаковых реализаций, потому что java имеет дело с примитивными массивами, но это, по крайней мере, незначительное раздражение, а не проблема с проблемой прерывания транзакции, чтобы оправдать 10-кратное повышение производительности.
.slice
- только один пример, большинство других операций с массивами, похоже, страдают от одной и той же проблемы. Почему это должно быть так?
Обновить, вот что я нахожу еще более шокирующим:
val seq = new scala.util.Random().alphanumeric.take(1000).toIndexedSeq
(1 to 20).map { _ => bm(1000) { seq.slice(100,200) } }.sum / 20
Это составляет около 5-6 миллионов ломтиков в секунду для меня. Но это:
import scala.collections.JavaConversions._
(1 to 20).map { _ => bm(1000) { seq.subList(100,200) } }.sum / 20
составляет от 12 до 15 миллионов! Разумеется, это не порядок разницы по величине, как в случае с массивами, но (1) особой обработки примитивов здесь нет, поэтому было бы совершенно тривиально просто реализовать с использованием стандартного инструментария Java, и (2) сборник является неизменным... как трудно можно вернуть ссылку на диапазон индексов???