性能 – Erlang:以有效的方式从输入流中读取

我正在编写一个从输入流中读取的程序,即

erl -run p main -noshell -s erlang halt < input

问题是使用这个读取函数需要花费大量时间来读取它(输入流很大):

read_input(L) ->
    case io:get_line("") of
        eof ->
            lists:reverse(L);
        E0 ->
            read_input([E0|L])
    end.

我一直在寻找更有效的替代方案,但我一无所获.我试过用它来读取文件

{ok, Binary} = file:read_file("input")

这远远高效得多.问题是我必须在名称未知的平台上运行此程序,所以我需要一些替代方法来执行此操作.另外,我不能选择运行时使用的标志,例如flag -noinput无法添加到命令行.

无论您给予什么帮助,都会受到欢迎.

最佳答案
虽然Steve’s solution是我所知道的最快的解决方案,但可以使用具有相当好性能的文件模块解决方案:

-module(p).

-export([start/0]).

-define(BLK_SIZE, 16384).

start() ->
    do(),
    halt().

do() ->
    Bin = read(),
    io:format("~p~n", [byte_size(Bin)]).

read() ->
    ok = io:setopts(standard_io, [binary]),
    read(<<>>).

read(Acc) ->
    case file:read(standard_io, ?BLK_SIZE) of
        {ok, Data} ->
            read(<<Acc/bytes, Data/bytes>>);
        eof ->
            Acc
    end.

它适用于调用,如:

erl -noshell -s p < input

请注意,这两种方法都可以用于面向行的输入,使用端口或文件的{line,Max_Line_Size}选项:read_line / 1用于文件模块解决方案.从版本17开始(如果我没记错),文件中存在固定的性能错误:read_line / 1我发现它现在很好.无论如何,你不应该期望Perl的性能和舒适度.

转载注明原文:性能 – Erlang:以有效的方式从输入流中读取 - 代码日志