Sas*_* B. 1 ruby performance benchmarking compare elixir
请帮助我解决有关Elixir与Ruby性能的基准问题.
我尝试在两种语言中实现相同的阶乘,而Ruby显示出比Elixir更好的结果:
# ruby_factorial_with_iterator.rb
def factorial_with_iterator(n)
res = 1
(1..n).each{|time| res *= time}
res
end
p "factorial_with_iterator(200000)"
p factorial_with_iterator(200000)
Run Code Online (Sandbox Code Playgroud)
运行后:
$ time ruby ruby_factorial_with_iterator.rb
real 0m18.378s
user 0m17.348s
sys 0m0.844s
Run Code Online (Sandbox Code Playgroud)
和两个Elixir例子:
# elixir_factorial_with_iterator.exs
defmodule FactorialWithIterator do
def of(n) do
Enum.reduce(1..n, 1, &*/2)
end
end
IO.puts "Factorial of 200000: "
IO.puts FactorialWithIterator.of(200000)
Run Code Online (Sandbox Code Playgroud)
运行后:
$ time elixir elixir_factorial_with_iterator.exs
real 1m1.735s
user 1m1.556s
sys 0m0.104s
Run Code Online (Sandbox Code Playgroud)
另一个例子:
# elixir_factorial_with_recursion.exs
defmodule FactorialWithRecursion do
def of(0), do: 1
def of(n) when n > 0 do
n * of(n - 1)
end
end
IO.puts "Factorial of 200000: "
IO.puts FactorialWithRecursion.of(200000)
Run Code Online (Sandbox Code Playgroud)
运行后:
$ time elixir elixir_factorial_with_recursion.exs
real 1m7.149s
user 1m6.248s
sys 0m0.092s
Run Code Online (Sandbox Code Playgroud)
为什么会有这么大的差异:Elixir - 1m1s和Ruby--只需18s?或者如何在Elixir中编写正确的迭代代码?
PS环境:
小智 10
正如其中一条评论所述,您正在使用它time,它也会启动VM,并且在elixir的情况下,将代码编译为BEAM字节码.为避免计算所有这些,您应该使用语言本身的基准测试工具.
我很好奇,所以我尝试自己对这些功能进行基准测试.
我用了:
bencheeelixir:https://github.com/PragTob/bencheebenchmark-ips对于ruby:https://github.com/evanphx/benchmark-ips红宝石:
require 'benchmark/ips'
def factorial_with_iterator(n)
res = 1
(1..n).each{|time| res *= time}
res
end
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('factorial_with_iterator.rb') do
factorial_with_iterator(200000)
end
x.compare!
end
Run Code Online (Sandbox Code Playgroud)
药剂:
defmodule Factorial do
def iter(n) do
Enum.reduce(1..n, 1, &*/2)
end
def recur(0), do: 1
def recur(n) when n > 0 do
n * recur(n - 1)
end
end
Benchee.run(%{
"factorial_with_iter.ex" => fn -> Factorial.iter(200000) end,
"factorial_with_recur.ex" => fn -> Factorial.recur(200000) end
})
Run Code Online (Sandbox Code Playgroud)
我得到了这些结果:
红宝石:
Warming up --------------------------------------
factorial_with_iterator.rb
1.000 i/100ms
Calculating -------------------------------------
factorial_with_iterator.rb
0.033 (± 0.0%) i/s - 1.000 in 29.994713s
Run Code Online (Sandbox Code Playgroud)
药剂:
Name ips average deviation median 99th %
factorial_with_iter.ex 0.0395 25.29 s ±0.00% 25.29 s 25.29 s
factorial_with_recur.ex 0.0368 27.17 s ±0.00% 27.17 s 27.17 s
Comparison:
factorial_with_iter.ex 0.0395
factorial_with_recur.ex 0.0368 - 1.07x slower
Run Code Online (Sandbox Code Playgroud)
因此,这些结果显示Elixir稍微快一些,使用Ruby的实现需要大约30秒,而Elixir需要大约25秒和大约27秒.
但是,使用"每秒迭代次数",对于花费时间超过一秒的功能可能有点"错误".所以我也尝试了更低的输入.我用了1_000而不是200_000,得到了这些结果:
红宝石:
Warming up --------------------------------------
factorial_with_iterator.rb
169.000 i/100ms
Calculating -------------------------------------
factorial_with_iterator.rb
1.750k (± 8.0%) i/s - 8.788k in 5.064619s
Run Code Online (Sandbox Code Playgroud)
药剂:
Name ips average deviation median 99th %
factorial_with_recur.ex 3.15 K 317.36 ?s ±12.72% 306 ?s 481.87 ?s
factorial_with_iter.ex 3.02 K 331.13 ?s ±16.83% 316 ?s 559 ?s
Comparison:
factorial_with_recur.ex 3.15 K
factorial_with_iter.ex 3.02 K - 1.04x slower
Run Code Online (Sandbox Code Playgroud)
奇怪的是,这表明Elixir比Ruby快得多.对于这两种实现,Elixir每秒能够执行超过3k次迭代,其中Ruby每秒只能执行1.75k迭代.
使用: