【发布时间】:2013-11-20 03:45:52
【问题描述】:
全部。
我想使用 Clojure 解析大日志文件。
并且每行记录的结构是“UserID,Lantitude,Lontitude,Timestamp”。
我实施的步骤是:
----> 读取日志文件 & 获取 top-n 用户列表
----> 查找每个 top-n 用户的记录并存储在单独的日志文件(UserID.log)中。
实现源码:
;======================================================
(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"))))
))
;======================================================
我在 REPL 中使用命令 (parse-file "./DATA/log.log" 3) 测试了这个 clj,并得到了结果:
记录-----大小-----时间----结果
1,000-------42KB-----
10,000--------420KB----
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 的新手,任何建议或解决方案都将不胜感激~
谢谢
【问题讨论】:
标签: clojure out-of-memory