Elixir 长生不老药;Benchwarmer的结果截然不同

Elixir 长生不老药;Benchwarmer的结果截然不同,elixir,benchmarking,Elixir,Benchmarking,我正在尝试对快速排序算法与枚举排序算法进行基准测试。我从benchfella和benchwarmer得到了截然不同的结果 摘要: Benchfella Benchwarmer Enum.sort 8920.47 µs/op 2418767.00 μs/op QuickSort 16660.45 µs/op 15745.04 μs/op 详细信息: Benchfella

我正在尝试对快速排序算法与枚举排序算法进行基准测试。我从
benchfella
benchwarmer
得到了截然不同的结果

摘要:

               Benchfella        Benchwarmer 
Enum.sort       8920.47 µs/op    2418767.00 μs/op
QuickSort      16660.45 µs/op      15745.04 μs/op

详细信息:

               Benchfella        Benchwarmer 
Enum.sort       8920.47 µs/op    2418767.00 μs/op
QuickSort      16660.45 µs/op      15745.04 μs/op
以下是我的基准:

defmodule Thing do
  defstruct [:key]
end

defmodule QuickSort do
  def qsort([]), do: []
  def qsort([pivot | rest]) do
    {left, right} = Enum.partition(rest, fn(x) -> x.key < pivot.key end)
    qsort(left) ++ [pivot] ++ qsort(right)
  end
end

defmodule Bench do
  use Benchfella
  Benchfella.start

  bench "QuickSort", [list: gen()] do
    QuickSort.qsort(list)
  end

  bench "Enum.sort", [list: gen()] do
    Enum.sort(list, fn(x, y) -> x.key > y.key end)
  end

 def gen, do: for _ <- 1..10000, do: %Thing{key: :rand.uniform}

  # Tests
  list = for _ <- 1..10000, do: %Thing{key: :rand.uniform}
  sorted = Enum.sort_by(list, &(&1.key))
  true = sorted == QuickSort.qsort(list)
end
以下是
钳工
的输出:

$ iex -S mix
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.3.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> list = Bench.gen
[%Thing{key: 0.29976857621751096}, %Thing{key: 0.42956956935048163},
 %Thing{key: 0.8682735084348573}, %Thing{key: 0.13149039866062429},
 %Thing{key: 0.5315758481143932}, %Thing{...}, ...]

iex(2)> Benchwarmer.benchmark fn -> QuickSort.qsort list end
*** #Function<20.52032458/0 in :erl_eval.expr/5> ***
1.9 sec    127 iterations   15745.04 μs/op

[%Benchwarmer.Results{args: [], duration: 1999619,
  function: #Function<20.52032458/0 in :erl_eval.expr/5>, n: 127, prev_n: 64}]

iex(3)> Benchwarmer.benchmark fn -> Enum.sort(list, fn(x, y) -> x.key > y.key end) end
*** #Function<20.52032458/0 in :erl_eval.expr/5> ***
2.4 sec      1 iterations   2418767.0 μs/op

[%Benchwarmer.Results{args: [], duration: 2418767,
  function: #Function<20.52032458/0 in :erl_eval.expr/5>, n: 1, prev_n: 1}]
$iex-S混合
Erlang/OTP19[erts-8.1][source][64位][smp:8:8][async threads:10][hipe][kernel poll:false][dtrace]
交互式长生不老药(1.3.3)-按Ctrl+C退出(键入h()回车以获取帮助)
iex(1)>列表=Bench.gen
[%Thing{key:0.29976857621751096},%Thing{key:0.42956956935048163},
%事物{key:0.8682735084348573},%Thing{key:0.1314903986062429},
%事物{key:0.531575841143932},%Thing{…},]
iex(2)>Benchwarmer.benchmark fn->QuickSort.qsort列表结束
***#功能***
1.9第127节迭代15745.04μs/op
[%Benchwarmer.Results{args:[],持续时间:1999619,
函数:#函数,n:127,上一个n:64}]
iex(3)>Benchwarmer.benchmark fn->Enum.sort(列表,fn(x,y)->x.key>y.key结束)结束
***#功能***
2.4第1节迭代2418767.0μs/op
[%Benchwarmer.Results{args:[],持续时间:2418767,
函数:#函数,n:1,上一个n:1}]

这很可能是由测试shell中定义的函数引起的。在shell中,对代码进行求值,而不是编译。除了编译的模块外,不要对任何东西进行基准测试。在编译模块之外进行的任何基准测试或多或少都是无用的。

这很可能是由测试shell中定义的函数引起的。在shell中,对代码进行求值,而不是编译。除了编译的模块外,不要对任何东西进行基准测试。在编译模块之外进行的任何基准测试或多或少都是无用的。

看起来Erlang无法对REPL(模块外部)中直接声明的
fn
执行某些优化。如果我把Benchfella代码放在一个模块中,然后调用它,我会看到类似于Benchfella的结果,我还可以用
:timer.tc fn->Enum.sort(list,fn(x,y)->x.key
重现~2.5秒的计时。你在比较不同的框架和不同的代码结构,甚至是不同的数据。请重做你的例子,使只有一件事是不同的,否则就不可能进行任何比较。我不确定这是公平的给我一个-1的这个问题。我想问的是,为什么“不同的框架和不同的代码结构”会产生不同的结果,哪些是值得信任的。我认为这是一个非常有效的问题,
Elixir
的初学者会发现这个问题很有用。看起来Erlang无法对REPL中直接声明的
fn
执行一些优化(在模块之外)。如果我把Benchfella代码放在一个模块中,然后调用它,我会看到类似于Benchfella的结果,我还可以用
:timer.tc fn->Enum.sort(list,fn(x,y)->x.key
重现~2.5秒的计时。你在比较不同的框架和不同的代码结构,甚至是不同的数据。请重做你的例子,使只有一件事是不同的,否则就不可能进行任何比较。我不确定这是公平的给我一个-1的这个问题。我想问的是,为什么“不同的框架和不同的代码结构”会产生不同的结果,哪些是值得信任的。我认为这是一个非常有效的问题,
Elixir
的初学者会发现这个问题很有用。谢谢。这就是我要找的。谢谢。这就是我要找的。