【问题标题】:Why does my escript crash the interpreter?为什么我的 escript 会使解释器崩溃?
【发布时间】:2016-09-26 00:49:03
【问题描述】:

我有一个读取 csv 文件 (100M) 的小程序。问题是我的程序使 Erlang 解释器崩溃:

Crash dump was written to: erl_crash.dump
eheap_alloc: Cannot reallocate 3563526520 bytes of memory (of type "heap").
Aborted

这是程序:

readlines(FileName) ->
    {ok, Device} = file:open(FileName, [read]),
    try get_all_lines(Device)
      after file:close(Device)
    end.


get_all_lines(Device) ->
    case io:get_line(Device, "") of
        eof -> [];
        Line -> [Line | get_all_lines(Device)]
    end.

我愿意:

Path="...csv".
Lines=tut6:readlines(Path).

这会导致崩溃。

谁能告诉我问题是什么?也许我的程序有问题?如何避免崩溃?

提前致谢

【问题讨论】:

  • 它是否适用于较小的文件?
  • 你对每一行分别做了什么?通过逐行处理文件而不是将所有行收集到一个列表中,您可能会获得更大的成功。
  • @A.萨里德。它确实适用于较小的文件。
  • @nu-ex。是的,你可能是对的。但无论如何,我需要将 CSV 内容存储在列表和哈希表等中。所以也许内存使用仍然会使解释器崩溃。你以前听说过这样的事情吗?
  • 在操作之前将 100MB 文件加载到内存中并不是我遇到的要求。你能告诉我们更多关于你正在尝试做的事情吗?您可以考虑将 CSV 数据导入数据库,例如 mnesia、DETS 甚至 PostgreSQL 或 MySQL 并根据需要获取。

标签: erlang


【解决方案1】:

试试

{ok, Device} = file:open(FileName, [read, binary]),

然后重新考虑你真正在做什么。

【讨论】:

    【解决方案2】:

    您是否意识到 3563526520 是 3.3 GB?你的系统有多少内存?巨大的内存消耗源于您选择了读取行的最优化算法:

    1. 在对它们进行操作之前,您尝试将所有行读入内存
    2. 您选择将文本表示为列表,从文件中读取的每个字符使用 8 个字节(或在 64 位系统上为 16 个字节)
    3. 您不使用尾递归,这意味着编译器无法优化您的代码以提高内存效率

    所以,修复代码:

    1. 一次读取一行,然后对其进行解析和处理,并将其存储为 Erlang 术语而不是原始输入数据
    2. 按照 Hynek -Pichi- Vychodil 的建议,将行读取为二进制文件
    3. 使读取文件的函数为尾递归

    如果您想知道如何正确实现此类函数,Learn You Some Erlang 对尾递归函数进行了精彩的讨论。

    如果函数以尾递归方式编写,整个算法可能如下所示:

    get_all_lines(Device) ->
        get_all_lines(Device, []).
    
    get_all_lines(Device, List) ->
        case io:get_line(Device, "") of
            eof ->
                lists:reverse(List);
            Line ->
                Data = process_line(Line),
                get_all_lines(Device, [Data | List])
        end.
    

    【讨论】:

    • 嗨 Amiramix。我应该如何表示文本?你能举个例子吗? :)
    • @JeniaIvanov 如果您以二进制模式打开文件[read, binary],那么来自设备的任何读取操作都将返回二进制而不是列表(包括示例代码中的io:get_line/2)。如果您想知道如何处理二进制文件,那么这个介绍应该会有所帮助:learnyousomeerlang.com/starting-out-for-real
    猜你喜欢
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    相关资源
    最近更新 更多