ETS性能的减慢

0xA*_*xAX 6 performance elixir ets

我围绕ets表的选择性能进行了一些测试,并注意到了奇怪的行为。例如,我们有一个简单的ets表(没有任何特定选项),该表存储键/值-随机字符串和数字:

:ets.new(:table, [:named_table])

for _i <- 1..2000 do
    :ets.insert(:table, {:crypto.strong_rand_bytes(10) 
    |> Base.url_encode64 
    |> binary_part(0, 10), 100})
end
Run Code Online (Sandbox Code Playgroud)

还有一个具有已知密钥的条目:

:ets.insert(:table, {"test_string", 200})
Run Code Online (Sandbox Code Playgroud)

现在有一个简单的愚蠢的基准测试函数,它试图test_string从ets表中多次选择并测量每次选择的时间:

test_fn = fn() ->
  Enum.map(Enum.to_list(1..10_000), fn(x) ->
    :timer.tc(fn() ->
      :ets.select(:table, [{{:'$1', :'$2'}, 
                           [{:'==', :'$1', "test_string"}], 
                           [:'$_']}])
    end)
  end) |> Enum.unzip
end
Run Code Online (Sandbox Code Playgroud)

现在,如果我看看最大时间,Enum.max(timings)它将返回的值大约是所有其他选择值的10倍。因此,例如:

iex(1)> {timings, _result} = test_fn.()
....
....
....
iex(2)> Enum.max(timings)
896
iex(3)> Enum.sum(timings) / length(timings)
96.8845
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到最大值几乎是平均值的10倍。

这里发生了什么事?它与GC,内存分配时间或诸如此类有关吗?您是否有任何想法,为什么从ets表中进行选择有时会导致这种变慢,或者如何进行分析。

UPD。

这是时序分布图: 在此处输入图片说明

Hel*_*rld 4

match_spec,第二个参数select/2使其变慢。

根据此问题
Erlang: ets select and match Performance的回答

In trivial non-specific use-cases, select is just a lot of work around match.  
In non-trivial more common use-cases, select will give you what you really want a lot quicker.
Run Code Online (Sandbox Code Playgroud)

set另外,如果您使用或类型处理表ordered_set,要根据键获取值,请改用lookup/2,因为它要快得多。
在我的电脑上,以下代码

  def lookup() do
    {timings, _} = Enum.map(Enum.to_list(1..10_000), fn(_x) ->
      :timer.tc(fn() ->
        :ets.lookup(:table, "test_string")
      end)
    end) |> Enum.unzip
    IO.puts Enum.max(timings)
    IO.puts Enum.sum(timings) / length(timings)
  end
Run Code Online (Sandbox Code Playgroud)

打印

0 
0.0
Run Code Online (Sandbox Code Playgroud)

当你的打印出来的时候

16000
157.9
Run Code Online (Sandbox Code Playgroud)

如果您有兴趣,可以在这里找到 ets:select 的 NIF C 代码。
https://github.com/erlang/otp/blob/9d1b3bb0db87cf95cb821af01189f6d6be072f79/erts/emulator/beam/erl_db.c