2016-08-12 5 views
1

Я попытался реализовать итеративный алгоритм с использованием диапазона. Он работал хорошо, поэтому я попытался сделать его параллельным, используя метод par, и он выбрал java.lang.OutOfMemoryError: Java heap space. Я обнаружил, что ParRange выделяет много памяти в конструкторе. Это правильное поведение ParRange? Я ожидал бы, что он ведет себя аналогично Range и выделяет данные только в том случае, если они необходимы.Scala ParRange потребление памяти

Вы можете легко воспроизвести его:

scala> collection.parallel.immutable.ParRange(1, 50000000, 1, true) java.lang.OutOfMemoryError: Java heap space

ответ

1

Я думаю, что вы нашли своего рода "ошибка".

Немного подробней.

  1. Если вы посмотрите в OOM StackTrace более точно - Скала (по неизвестной причине) является применение простого toString метода на ParRange.scala:35 класса. 50 миллионов номеров, объединенных в огромную строку, дают вам больше, чем Gb и приводят к OOM.

  2. OOM происходит только при выполнении в console. Простое автономное приложение с main работает нормально (если вы не вызываете toString)

  3. 0 приблизительно Range? Действительно, тот же код с Range вместо ParRange работает perfeclty. Причина довольно проста: метод ToString является перекрываться там, и не пытаться вывести все элементы, а не только первые несколько ...

Я предлагаю вам следующий обходной путь, чтобы сделать код работы:

def parRangeBuilder(start: Int, end: Int, step: Int, include: Boolean) = { 
    new ParRange(
     if (include) 
     new Range.Inclusive(start, end, step) 
     else 
     new Range(start, end, step) 
    ) { 
    override def toString = s"LazyParRange(${range.size})" // fix itself... 
    } 
    } 
Смежные вопросы