2014-01-24 2 views
1

doseq으로 반복하지만 첫 번째 요소의 일부분을 고정하면 지연 시퀀스의 동작을 이해하고 싶습니다.line-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의 "head of the list"에서처럼 첫 번째 요소라고 생각하면 약간의 잘못된 이름입니다. 문제는 시퀀스에 대한 참조를 보유하고 있습니다.

+0

참고 : 저는 멀티 기가 바이트 파일을 다루고 있습니다. lazily가 생산되고 소비 되더라도'let '이 서열을 유지한다고 말하는 겁니까? 위의 작업을 수행하려면 어떤 구문을 사용해야합니까? 나는 loop-seq의 꼬리 부분에 loop + recur를 써서 이것을 다시 작성했다. 그리고 RAM 사용은 상당히 작다. 그러나 그것은 거의 멋지지 않게 보입니다. seq-holding하지 않고도 lazily-evaluate지도를 얻는 방법이 있습니까? – Joe

+0

그럴 필요가 없다고 대답 할 필요가 없다면 바인딩이 '전체로서의 게으른 시퀀스'가 아닌 cons-cell-type 요소에 있다는 것을 깨달았습니다. 필자가해야 할 일은'파싱 된 라인'을'doseq' 바인딩에 넣는 것이었다. – Joe

+1

컴파일러는 마지막으로 참조되는 즉시, 즉 doseq가 시작될 때'파싱 된 라인 '을 여기에서 해제해야합니다. 주석이 달린 행이 커다란 게으른 순서를 참조하지 않는 한 여기에 게시 된 코드는 많은 메모리를 필요로하지 않습니다. – amalloy

1

JVM은 일단 Java 힙의 일부가되면 OS로 메모리를 반환하지 않으며 사용자가 다르게 구성하지 않으면 기본 최대 힙 크기가 매우 큽니다 (일반적으로 사용 가능한 RAM의 1/4). 따라서 "Josh가 OutOfMemoryError를 던졌습니다."보다는 "Gosh, 이것은 많은 메모리를 차지합니다"와 같은 모호한 문제 만 경험한다면 JVM을 원하는대로 조정하지 않았을 것입니다. 행위. partition-bylittle입니다. 한 번에 하나 또는 두 개의 파티션을 보유하고 있지만 파티션이 큰 경우가 아니면이 코드로 힙 공간이 부족해서는 안됩니다. -Xmx100m을 설정하거나 프로그램의 적절한 힙 크기를 생각하고 문제가 있는지 확인하십시오.

+0

도움 주셔서 감사합니다. 예, 파티션이 매우 큽니다 (~ OTOO 1GB). 코드를 두 번 반복했고, 월요일에 특성과 업데이트를 확인해야합니다. 이 작업이 완료되면 JVM이 많은 RAM을 반환하므로 의심 스럽습니다. 내 힙은 충분히 크고 (4GB) 크게 설정되었지만 데이터 크기에 따라 사용량이 증가하고 큰 실제 데이터에 대한 소비량을 외삽하는 것으로 나타났습니다. – Joe

+0

re'partition-by' 나는 게으른 seqs의 게으른 seqs를 반환했다고 들었습니다. 파티션 자체가 실현되고 저장된다고 말하고 있습니다. 파티션이 전체적으로 저장되어 있다면 내 질문에 답할 것입니다 (매우 큽니다). – Joe

+0

실제로 열망하는 seqs의 게으른 seq. – amalloy