Я написал приложение Scala (2.9.1-1), которому необходимо обработать несколько миллионов строк из запроса к базе данных. Я преобразовываю ResultSet
в Stream
, используя метод, показанный в ответе на один из моих предыдущих вопросов:
class Record(...)
val resultSet = statement.executeQuery(...)
new Iterator[Record] {
def hasNext = resultSet.next()
def next = new Record(resultSet.getString(1), resultSet.getInt(2), ...)
}.toStream.foreach { record => ... }
, и это сработало очень хорошо.
Поскольку тело замыкания foreach
очень интенсивно использует ЦП, и как свидетельство практичности функционального программирования, если я добавлю .par
перед foreach
замыкания выполняются параллельно без каких-либо других усилий, за исключением того, чтобы убедиться, что тело замыкания является потокобезопасным (оно написано в функциональном стиле без изменяемых данных, кроме печати в потокобезопасный журнал).
Однако меня беспокоит потребление памяти. Является ли .par
причиной загрузки всего набора результатов в ОЗУ, или параллельная операция загружает только столько строк, сколько у нее активных потоков? Я выделил 4G для JVM (64-разрядный с -Xmx4g
), но в будущем я буду запускать его на еще большем количестве строк и беспокоиться о том, что в конечном итоге я получу нехватку памяти.
Существует ли лучший шаблон для выполнения такой параллельной обработки функциональным образом? Я показывал это приложение своим коллегам как пример ценности функционального программирования и многоядерных машин.