Обновление: Эликсир работает не так медленно, как мой алгоритм. Мои алгоритмы не были даже сравнением яблок с яблоками. См. Ответы Романа ниже для эквивалентных алгоритмов Ruby и Go. Также благодаря Хосе мой медленный алгоритм можно значительно ускорить, просто добавив префикс MIX_ENV=prod. Я обновил статистику в вопросе.
Первоначальный вопрос: я работаю над задачами Project Euler на нескольких языках, просто чтобы посмотреть, насколько производительны и быстры языки. В задаче №5 нас просят найти наименьшее положительное число, которое без остатка делится на все числа. от 1 до 20.
Я реализовал решение на нескольких языках. Вот статистика:
- Go 1.4.2 : 0.58s
- Рубин 2.2 МРТ: 6,7 с
- Эликсир 1.0.5 (мой первый алгоритм): 57 с.
- Эликсир 1.0.5 (мой первый алгоритм с префиксом MIX_ENV=prod): 7,4 с.
- Эликсир 1.0.5 (алгоритм, эквивалентный Роману Го): 0,7 с.
- Эликсир 1.0.5 (эквивалентный алгоритм Roman's Ruby): 1,8 с.
Почему производительность Эликсира такая низкая? Я пытался использовать одни и те же оптимизации на всех языках. Предупреждение: я новичок в FP и Эликсире.
Могу ли я что-нибудь сделать, чтобы улучшить производительность в Эликсире? Если вы использовали какие-либо инструменты профилирования для поиска лучшего решения, не могли бы вы включить их в ответ?
In Go:
func problem005() int {
i := 20
outer:
for {
for j := 20; j > 0; j-- {
if i%j != 0 {
i = i + 20
continue outer
}
}
return i
}
panic("Should have found a solution by now")
}
В Руби:
def self.problem005
divisors = (1..20).to_a.reverse
number = 20 # we iterate over multiples of 20
until divisors.all? { |divisor| number % divisor == 0 } do
number += 20
end
return number
end
В Эликсире:
def problem005 do
divisible_all? = fn num ->
Enum.all?((20..2), &(rem(num, &1) == 0))
end
Stream.iterate(20, &(&1 + 20))
|> Stream.filter(divisible_all?)
|> Enum.fetch! 0
end