为什么我的 IO 在 Erlang 中运行得这么慢?

发布于 2024-12-01 16:04:16 字数 775 浏览 3 评论 0原文

我正在将文本文件中写入的 512^2 个空格分隔的双精度数通过管道传输到标准输入读取到我的 Erlang 程序中。

在 Erlang 中,这需要 2 分 25 秒,在等效的 Haskell 程序中,需要 3 秒,所以我必须以某种方式反对 Erlang 的做法。

我是否以一种愚蠢的方式使用了 Erlang 的 IO 原语,或者我的程序还有其他问题吗?

请注意,我不关心结果列表中值的顺序,因此没有反向操作。

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 ()

非常感谢您的帮助。

I'm reading 512^2 whitespace delimited doubles written in a text file to my Erlang program by piping them to stdin.

In Erlang this takes 2m25s, in an equivalent Haskell program it takes 3s, so I must be going against the Erlang way of doing it in some way.

Am I using Erlang's IO primitives in a stupid way, or is there something else wrong with my program?

Note that I don't care about the order of the values in the resulting list, so no reverse operation.

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 ()

Thanks very much for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人事已非 2024-12-08 16:04:16

不,你没有以愚蠢的方式使用 Erlang IO。这是 Erlang IO 的问题,众所周知,它的速度并不快。 Erlang 广泛用于编写服务器,因此面向 socked 的 IO 得到了很好的调整。面向块的文件 IO 并没有那么糟糕,但是使用 io 模块来处理 stdin 效果不佳。 Erlang 并未广泛用于此类工作。如果您需要这种操作,您应该编写自己的专门输入例程。您有两个选择:

  1. 使用 io 以原始和二进制模式从 file 读取,然后使用二进制模块拆分输入,然后使用 list_to_float/1 进行转换。
  2. 使用专门的面向端口的标准输入读取例程(例如您可以在 http://shootout.alioth.debian.org/u64q/program.php?test=regexdna&lang=hipe&id=7 注意用于 vm 调用的 read/0 函数和 -noshell -noinput 参数),然后按照第一个选项继续。

在我看来(以及根据我以前的经验),您的案例中最大的影响来自于使用类似扫描的输入例程进行浮点解码,辅之以缓慢(重复)的 io 调用,但它需要一些重要的分析来证明这一点。

No, you are not using Erlang IO in stupid way. It's problem with Erlang IO which is not well known to be fast. Erlang is widely used for writing servers so socked oriented IO is excellent tuned. Block oriented file IO is not so bad, but using io module for working with stdin doesn't work well. Erlang is not widely used for this kind of work. If you need this kind of operations you should write your own specialized input routine. You have two options there:

  1. use io for reading from file in raw and binary mode and then split input using binary module and then use list_to_float/1 for conversion.
  2. use specialized port oriented stdin reading routine (as you can see for example in http://shootout.alioth.debian.org/u64q/program.php?test=regexdna&lang=hipe&id=7 note read/0 function and -noshell -noinput parameters for vm invocation) and then continue as in first option.

In mine opinion (and from mine previous experience) biggest impact in your case comes from using scan-like input routine for float decoding seconded by slow (repeated) io invocation, but it would need some nontrivial profiling to prove it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文