我的Erlang IO为什么运行如此缓慢?

9
我正在将一个由512^2个以空格分隔的双精度浮点数组成的文本文件通过stdin管道输入到我的Erlang程序中进行读取。
在Erlang中,这需要花费2分钟25秒的时间,在等效的Haskell程序中只需要3秒钟的时间,所以我一定是以某种方式违反了Erlang的做法。
我是否以一种愚蠢的方式使用了Erlang的IO原语,或者我的程序还有其他问题?
请注意,我不关心结果列表中的值的顺序,因此不需要进行reverse操作。
Erlang:
-module(iotest).

-import(io).

-export([main/0]).

main() ->
    Values = read(),
    io:write(Values).

read() -> read([]).

read(Acc) ->
    case io:fread("", "~f") of
        {ok, Value} -> read([Value | Acc]);
        eof -> Acc
    end.

Haskell:

module IOTest (
    main
) where

main :: IO ()

main = do
    text <- getContents
    let values = map read (words text) :: [Double]
    putStrLn $ show values
    return ()

非常感谢您的帮助。
谢谢。

它似乎还会生成数字列表的反向。 - augustss
1个回答

9
不,你没有愚蠢地使用Erlang IO。问题在于Erlang IO并不被广泛认为是快速的。Erlang被广泛用于编写服务器,因此面向套接字的IO得到了良好的调整。块定向文件IO并不那么糟糕,但使用io模块处理stdin的工作效果不佳。Erlang并不被广泛用于这种类型的工作。如果您需要这种类型的操作,则应编写自己的专业输入程序。您有两个选择:
1.使用io以原始和二进制模式从文件中读取数据,然后使用二进制模块拆分输入,然后使用list_to_float/1进行转换。
2.使用专门的基于端口的stdin读取例程(例如,在http://shootout.alioth.debian.org/u64q/program.php?test=regexdna&lang=hipe&id=7中可以看到read/0函数和-noshell-noinput参数用于vm调用),然后继续第一种选择的步骤。
在我看来(并根据我的以往经验),你的情况中最大的影响来自于使用类似扫描的输入程序进行浮点解码,其次是缓慢(重复)的io调用,但需要进行一些非常规的分析来证明它。

谢谢。我已经修改了我的程序,使其运行在两个阶段,在第一个阶段读取文件并将其保存为 Erlang 术语。当我实际运行程序时,它现在读取 Erlang 术语,只需要几秒钟即可完成。 - Steve Johnson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接