Подтвердить что ты не робот

Почему Array.slice так (отвратительно!) Медленно?

Вот мой тестовый код:

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) сборник является неизменным... как трудно можно вернуть ссылку на диапазон индексов???

4b9b3361

Ответ 1

Он был исправлен в scala 2.12.