Почему мой ввод-вывод работает так медленно в Эрланге? - PullRequest
8 голосов
/ 29 августа 2011

Я читаю 512 ^ 2 двойных символа, разделенных пробелами, записанных в текстовом файле, в мою программу Erlang путем передачи их в stdin.

В Erlang это занимает 2м25 с, в эквивалентной программе на Haskell это занимает 3 с, поэтому я, должно быть, иду в некотором смысле против Эрланга.

Я тупо использую примитивы ввода-вывода Эрланга или что-то не так с моей программой?

Обратите внимание, что мне не важен порядок значений в результирующем списке, поэтому нет обратной операции.

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

Большое спасибо за любую помощь.

1 Ответ

9 голосов
/ 29 августа 2011

Нет, вы не используете Erlang IO глупо. Это проблема с Erlang IO, который, как известно, не быстрый. Erlang широко используется для написания серверов, поэтому ориентированный на носок ввод-вывод отлично настроен. Блочный ориентированный файловый ввод-вывод не так уж и плох, но использование модуля io для работы со стандартным вводом не работает. Эрланг не широко используется для такого рода работ. Если вам нужны такие операции, вы должны написать собственную специализированную процедуру ввода. У вас есть два варианта:

  1. используйте io для чтения из файла в необработанном и двоичном режиме, а затем разделите ввод с помощью двоичного модуля и затем используйте list_to_float/1 для преобразования.
  2. использовать специализированную процедуру чтения стандартного порта, ориентированную на порт (как вы можете видеть, например, в http://shootout.alioth.debian.org/u64q/program.php?test=regexdna&lang=hipe&id=7 note read/0 function и -noshell -noinput параметры для вызова vm), а затем продолжить, как в первом варианте.

По моему мнению (и из моего предыдущего опыта) наибольшее влияние в вашем случае оказывает использование скан-подобной входной подпрограммы для декодирования с плавающей запятой, сопровождаемой медленным (повторным) вызовом io, но для этого потребуется некоторое нетривиальное профилирование, чтобы доказать это.

...