Clojure - 处理内存不足的大文件

标签 clojure memory-efficient file-processing

我正在处理 60GB 或更大的文本文件。这些文件被分成可变长度的标题部分和数据部分。我有三个功能:

  • head?区分标题行和数据行的谓词
  • process-header处理一个标题行字符串
  • process-data处理一个数据行字符串
  • 处理函数异步访问和修改内存数据库

  • 我从另一个 SO 线程推进了一种文件读取方法,它应该构建一个惰性的行序列。这个想法是用一个函数处理一些行,然后切换一次函数并继续处理下一个函数。
    (defn lazy-file
      [file-name]
      (letfn [(helper [rdr]
                (lazy-seq
                 (if-let [line (.readLine rdr)]
                   (cons line (helper rdr))
                   (do (.close rdr) nil))))]
        (try
          (helper (clojure.java.io/reader file-name))
          (catch Exception e
            (println "Exception while trying to open file" file-name)))))
    

    我将它与类似的东西一起使用
    (let [lfile (lazy-file "my-file.txt")]
      (doseq [line lfile :while head?]
        (process-header line))
      (doseq [line (drop-while head? lfile)]
        (process-data line)))
    

    尽管这可行,但由于以下几个原因,它的效率相当低:
  • 而不是简单地调用 process-head直到我得到数据,然后继续 process-data ,我必须过滤标题行并处理它们,然后重新解析整个文件并删除所有标题行以处理数据。这与 lazy-file 完全相反。打算做的。
  • 观察内存消耗告诉我,该程序虽然看起来很懒惰,但可以使用尽可能多的 RAM 来将文件保存在内存中。

  • 那么使用我的数据库的更有效、更惯用的方法是什么?

    一种想法可能是使用多方法来处理取决于 head? 的值的标题和数据。谓词,但我认为这会对速度产生一些严重的影响,特别是因为只有一次发生谓词结果从始终为真变为始终为假的情况。我还没有对此进行基准测试。

    使用另一种方式构建行序列并使用 iterate 解析它会更好吗? ?这仍然让我需要使用 :while 和 :drop-while,我猜。

    在我的研究中,多次提到使用 NIO 文件访问,这应该可以提高内存使用率。我还不知道如何在 clojure 中以惯用的方式使用它。

    也许我对大体的想法还没有把握,文件应该如何处理?

    与往常一样,非常感谢任何帮助、想法或指向 tuts 的指示。

    最佳答案

    您应该使用标准库函数。

    line-seq、with-open 和 doseq 可以轻松完成这项工作。

    符合以下条件的东西:

    (with-open [rdr (clojure.java.io/reader file-path)]
      (doseq [line (line-seq rdr)]
        (if (head? line)
          (process-header line)
          (process-data line))))
    

    关于Clojure - 处理内存不足的大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34329821/

    相关文章:

    clojure - 如何具体化 Prolog 的回溯状态以执行与 Clojure 中的 "lazy seq"相同的任务?

    linux - 如何使用粘贴/加入或 linux 或 perl 以有序方式有效地加入 'n' 个文件?

    c++ - 内存效率 - 循环中的 Eigen::VectorXd

    Clojure - 使用结果作为参数一遍又一遍地调用函数

    clojure - 使用 Datomic 返回 Map 而不是 Vector 时出错

    clojure - 运行 "gpg: decryption failed: secret key not available"时如何修复 "lein deploy clojars"?

    perl - 是否应该重用单个HTML::SimpleLinkExtor对象以提高内存效率?

    c++ - 文件处理(对于具有多个字段的文件)以及与之相关的问题

    python - 在python中处理大量文件

    python-3.x - 我正在尝试删除 python 中以/开头的文本行