все.
Я хочу разбирать большие файлы журнала с помощью Clojure.
И структура каждой записи строки - «UserID, Lantitude, Lontitude, Timestamp».
Мои реализованные шаги:
----> Читать файл журнала & Получить топ-N Список пользователей
----> Найти записи и хранения каждого топ-н пользователя в отдельный лог-файл (UserID.log).Clojure: Получить «OutOfMemoryError Java кучу пространства» при разборе большого файла журнала
Орудие исходный код:
;======================================================
(defn parse-file
""
[file n]
(with-open [rdr (io/reader file)]
(println "001 begin with open ")
(let [lines (line-seq rdr)
res (parse-recur lines)
sorted
(into (sorted-map-by (fn [key1 key2]
(compare [(get res key2) key2]
[(get res key1) key1])))
res)]
(println "Statistic result : " res)
(println "Top-N User List : " sorted)
(find-write-recur lines sorted n)
)))
(defn parse-recur
""
[lines]
(loop [ls lines
res {}]
(if ls
(recur (next ls)
(update-res res (first ls)))
res)))
(defn update-res
""
[res line]
(let [params (string/split line #",")
id (if (> (count params) 1) (params 0) "0")]
(if (res id)
(update-in res [id] inc)
(assoc res id 1))))
(defn find-write-recur
"Get each users' records and store into separate log file"
[lines sorted n]
(loop [x n
sd sorted
id (first (keys sd))]
(if (and (> x 0) sd)
(do (create-write-file id
(find-recur lines id))
(recur (dec x)
(rest sd)
(nth (keys sd) 1))))))
(defn find-recur
""
[lines id]
(loop [ls lines
res []]
(if ls
(recur (next ls)
(update-vec res id (first ls)))
res)))
(defn update-vec
""
[res id line]
(let [params (string/split line #",")
id_ (if (> (count params) 1) (params 0) "0")]
(if (= id id_)
(conj res line)
res)))
(defn create-write-file
"Create a new file and write information into the file."
([file info-lines]
(with-open [wr (io/writer (str MAIN-PATH file))]
(doseq [line info-lines] (.write wr (str line "\n")))
))
([file info-lines append?]
(with-open [wr (io/writer (str MAIN-PATH file) :append append?)]
(doseq [line info-lines] (.write wr (str line "\n"))))
))
;======================================================
Я испытал это CLJ в РЕПЛ с командой (синтаксический-файл "./DATA/log.log" 3), и получить результаты:
Записи ----- Размер ----- Время ---- Результат
1,000 ------- 42KB ----- < 1s ----- OK
10 000 ----- -420 КБ ---- < 1s ----- OK
100 000 ----- 4.3MB ---- 3s ------ OK
1,000,000 --- 43MB ----- 15s ----- OK
6,000,000 --- 258MB ----> 20M ---- "OutOfMemoryError Java куча пространства java.lang.String.substring (String. java: 1913) "
============================================================================================================================================== ==============
Вот вопрос:
1. как я могу исправить ошибку, когда я пытаюсь разобрать большой файл журнала, как> 200MB
2. как я могу оптимизировать функцию для работы быстрее?
3. Есть журналы размером более 1G, как с этим можно справиться.
Я еще новичок в Clojure, любое предложение или решение будет оценить ~
Благодаря
Я думал, что увеличение памяти будет просто лечить симптом, а не лечить болезнь, но ваша точка на * поддержании * лень велика. – Vidya