В настоящее время я очень заинтересован в изучении Эликсира, и мой типичный подход к изучению нового языка - это создание с ним простых программ.Почему этот код Эликсира так медленно?
Так что я решил написать (очень простой) Grep-подобные программы (или модуль), который показан здесь:
defmodule LineMatch do
def file(s, path) do
case File.open(path, [:read]) do
{:ok, fd} -> match s, fd
{_, error} -> IO.puts "#{:file.format_error error}"
end
end
defp match(s, fd) do
case IO.read fd, :line do
{:error, error} -> IO.puts("oh noez! Error: #{error}")
line -> match(s, line, fd)
end
end
defp match(s, line, fd) when line !== :eof do
if String.contains?(line, s) do
IO.write line
end
match(s, IO.read(fd, :line), fd)
end
defp match(_, _line, _) when _line === :eof do
end
end
Это, скорее всего, не самый изящный способ сделать это, и я также совершенно новый для функционального программирования, поэтому я не ожидал, что он будет очень быстрым. Но это не только не быстро, на самом деле это супер медленный. Так медленно, что я, вероятно, совершил какую-то сверхразумную ошибку.
Может ли кто-нибудь сказать мне, что это такое и как сделать его лучше?
Я обычно проверить код с отдельными .exs файл как
case System.argv do
[searchTerm, path] -> LineMatch.file(searchTerm, path)
_ -> IO.puts "Usage: lineMatch searchTerm path"
end
Благодарим за подробный ответ! Я обязательно попробую ваше предложение. Я использовал http://www.generatedata.com/ для генерации данных примера. Я все еще удивляюсь, почему это так медленно. Конечно, преобразование UTF-8 замедляет его, но я получил выход, как одна линия на 500 мс. – koehr
Я действительно сомневаюсь, что это конверсия UTF-8. Работа с файлами через File.read очень медленная, так как каждая транзакция ввода-вывода является сообщением между процессами в elixir. Почти всегда быстрее читать один большой кусок, а затем анализировать этот единственный бинарный файл. –