큰 json 파일 (3GB)을 구문 분석하고이 파일의 각 행에 대한 해시 맵을 반환합니다. 필자의 직감은 변환기를 사용하여 파일을 한 줄씩 처리하고 일부 선택된 필드 (파일의 바이트의> 5 %)가있는 벡터를 구성하는 것이 었습니다. 내가 JVisualVM와 과정을 시각화 할 때, 힙을 통해 성장Clojure Tranducers를 사용하여 큰 파일 구문 분석 : OutOfMemory 오류
(defn load-with!
"Load a file using a parser, a structure and a transducer."
[parser structure xform path]
(with-open [r (clojure.java.io/reader path)]
(into structure xform (parser r))))
(def xf (map #(get-in % ["experiments" "results"])))
(def parser (comp (partial map cheshire.core/parse-string) line-seq))
(load-with! parser (vector) xf "file.json")
file.json
{"experiments": {"results": ...}}
{"experiments": {"results": ...}}
{"experiments": {"results": ...}}
parser.clj :
그러나 다음 코드는에서 OutOfMemory 예외를 발생 프로세스가 충돌하기 전에 25GB를 초과합니다.
이 경우 적절한 변환기가 있습니까? 거기에 더 나은 대안이 있습니까?
함수 끝에 새 구조체를 반환해야한다는 요구 사항 중 하나입니다. 따라서, dosq을 사용하여 파일을 내부 처리 할 수 없습니다.
또한 파서와 변환기를 파일 형식에 맞게 변경해야합니다.
감사합니다.
코드를 완전히 이해하지 못했습니다. 파서의 역할은 무엇입니까? 통과되었지만 사용되지 않은 것 같습니다. 또한'(r)'표현은 아마도 당신이 원하는 것이 아니며 독자를 함수로 부릅니다. –
트랜스 듀서가 도움이되는 이유가 없습니다. 트랜스 듀서는 데이터에 대해 수행하려는 일련의 작업이있을 때 유용합니다. 변환기를 사용하면 버려 질 중간 데이터 구조를 만들지 않아도됩니다. 이 코드는 단지 한 가지만 수행합니다.'get-in'을 매핑합니다. 'into '는 non-lazy이다. 파일을 지연 처리 할 수 있습니까? 'for ','map' 또는'sequence' 변환기 함수를 사용하면 게이츠 시퀀스의 게으른 시퀀스를 만들 수 있습니까? 파일을 올바르게 처리하면 모든 파일 내용을 메모리에 보관하지 않고 각각을 처리 할 수 있습니다. – Mars
파서/변환기의 목표는 파일 형식 (예 : json, csv ...) 및 파일 내의 공급 업체 형식에 따라 작업을 쉽게 적용하는 것입니다. – fmind