Erlang翻译崩溃

时间:2016-05-27 15:43:45

标签: erlang

我有一个读取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).

这会导致崩溃。

有人可以告诉我这是什么问题吗?也许我的程序有问题?我怎样才能避免崩溃?

提前致谢

2 个答案:

答案 0 :(得分:5)

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

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

    1. 一次读取一行,然后解析并处理它并存储为Erlang术语而不是原始输入数据
    2. 按照Hynek -Pichi- Vychodil
    3. 的建议,将行读作二进制文件
    4. 使函数读取文件tail-recursive
    5. 如果您想知道如何正确实现这些函数,

      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.
      

答案 1 :(得分:1)

尝试

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

然后重新考虑你的真实情况。