2014-01-24 6 views
1

Я хотел бы понять поведение ленивой последовательности, если я перебираю doseq, но удерживаю часть первого элемента.Каково будет поведение линии-seq?

(with-open [log-file-reader (clojure.java.io/reader (clojure.java.io/file input-file-path))] 

    ; Parse line parse-line returns some kind of representation of the line. 
    (let [parsed-lines (map parse-line (line-seq log-file-reader)) 
      first-item (first parsed-lines)] 

      ; Iterate over the parsed lines 
      (doseq [line parsed-lines] 
      ; Do something with a side-effect 
     ))) 

Я не хочу сохранять ни один из этих списков, я просто хочу выполнить побочный эффект с каждым элементом. Я считаю, что без first-item проблем не возникнет.

У меня проблемы с памятью в моей программе, и я думаю, что, возможно, сохранение ссылки на что-то в начале последовательности parsed-line означает, что вся последовательность сохранена.

Какое здесь поведение? Если последовательность хранится, существует ли общий способ взять копию объекта и включить реализованную часть последовательности для сбора мусора?

ответ

2

Последовательность-холдинг здесь происходит

... 
(let [parsed-lines (map parse-line (line-seq log-file-reader)) 
... 

Последовательность строк в файле в настоящее время лениво производить и проанализирован, но вся последовательность удерживается на, в пределах объема let. Эта последовательность реализована в doseq, но doseq не проблема, она не поддерживает последовательность.

... 
(doseq [line parsed-lines] 
; Do something 
... 

Вы не обязательно заботиться о последовательности-холдинг в let, поскольку объем let ограничен, но здесь, вероятно ваш файл большой и/или вы остаетесь в пределах динамического объема let на некоторое время, или, возможно, вернуть закрытие, содержащее его в разделе «сделать что-то».

Обратите внимание, что удерживание на любом данном элементе последовательности, включая первое, не содержит последовательности. Термин head-holding немного неправильный, если вы считаете, что глава является первым элементом, как в «главе списка» в Prolog. Проблема заключается в ссылке на последовательность.

+0

FYI Я имею дело с файлами с несколькими гигабайтами. Вы говорите, что «пусть» сохраняет последовательность, даже если ее лениво производят и потребляют? Какой синтаксис я должен использовать, чтобы сделать это выше? Я только что переписал это с помощью цикла + recur на хвосте линии-seq, и использование ОЗУ было значительно меньше. Но это выглядит не так хорошо. Есть ли способ получить лениво оцененную карту в объеме без seq-hold? – Joe

+0

Не нужно отвечать, если вы этого не хотите, я понял, что привязка - это элемент cons-cell-type, а не «ленивая последовательность в целом». То, как я должен был это сделать, заключалось в том, чтобы поместить 'parsed-lines' в обязательную привязку. – Joe

+1

Компилятор должен выпустить 'parsed-lines' здесь, как только он ссылается последним, т.е. когда начинается доза. Код, размещенный здесь, не требует большой памяти, если только строки с комментариями не относятся к большой ленивой последовательности. – amalloy

1

JVM никогда не будет возвращать память ОС, как только она станет частью кучи java, и если вы не настроите ее по-другому, размер максимальной кучи по умолчанию довольно большой (обычно 1/4 доступной оперативной памяти). Поэтому, если вы испытываете только такие неопределенные проблемы, как «Gosh, это занимает много памяти», а не «Ну, JVM бросил OutOfMemoryError», вы, вероятно, просто не настроили JVM так, как вам хотелось бы акт. partition-by является маленьким нетерпением, поскольку он содержит один или два раздела в памяти сразу, но если ваши разделы не огромны, вы не должны выходить из кучи с этим кодом. Попробуйте установить -Xmx100m, или как вы думаете, это разумный размер кучи для вашей программы, и посмотрите, есть ли у вас проблемы.

+0

Спасибо за помощь. Да, разделы очень большие (~ OTOO 1 ГБ). Я несколько раз повторял код, мне нужно вернуться и подтвердить характеристики и обновление в понедельник. После завершения этой операции JVM возвращает много оперативной памяти, поэтому я подозрительный. Моя куча установлена ​​достаточно большой (4 ГБ), но я просто вижу увеличение использования с размером данных и экстраполяцию потребления для больших реальных данных, я думаю, что есть что-то. – Joe

+0

re 'partition-by' Я слышал, что он вернул ленивые слова ленивых секций. Вы говорите, что сами разделы реализованы и сохранены. Если разделы хранятся целыми, это ответ на мой вопрос (они очень большие). – Joe

+0

Ленивый ряд энергичных секций. – amalloy

Смежные вопросы