Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Elixir/Erlang中的(本地)Mnesia实例上实现最佳写入性能_Erlang_Elixir_Otp_Mnesia - Fatal编程技术网

在Elixir/Erlang中的(本地)Mnesia实例上实现最佳写入性能

在Elixir/Erlang中的(本地)Mnesia实例上实现最佳写入性能,erlang,elixir,otp,mnesia,Erlang,Elixir,Otp,Mnesia,短而甜;我正在建立一个新的项目,我可以用ETS来支持,但我更愿意用Mnesia来支持——因为像内置事务这样的东西可能会派上用场。我不关心复制和扩展到其他节点,这就是为什么我认为Mnesia的性能在ETS上有开销 zackehh:~/GitHub/my_project$ MIX_ENV=test mix bench Settings: duration: 1.0 s ## BasicBench [19:24:15] 1/4: retrieve key hit mnesia [19:

短而甜;我正在建立一个新的项目,我可以用ETS来支持,但我更愿意用Mnesia来支持——因为像内置事务这样的东西可能会派上用场。我不关心复制和扩展到其他节点,这就是为什么我认为Mnesia的性能在ETS上有开销

zackehh:~/GitHub/my_project$ MIX_ENV=test mix bench
Settings:
  duration:      1.0 s

## BasicBench
[19:24:15] 1/4: retrieve key hit mnesia
[19:24:23] 2/4: retrieve key hit
[19:24:30] 3/4: insert new key mnesia
[19:24:33] 4/4: insert new key

Finished in 25.24 seconds

## BasicBench
insert new key                 10000000   0.63 µs/op
retrieve key hit               10000000   0.64 µs/op
retrieve key hit mnesia        10000000   0.69 µs/op
insert new key mnesia            500000   4.70 µs/op
我运行了一些(本地)基准测试,很明显,Mnesia的读性能与之相当,但写性能要慢得多。我想知道是否有任何方法可以加快速度(例如关闭复制检查等)

其他信息:

记忆表:

[
    { :ram_copies, [node()] },
    { :local_content, true },
    { :attributes, [:key,:value] }
]
测试

  • ETS操作使用
    :ETS.lookup/2
    :ETS.insert/2
  • Mnesia操作使用
    :Mnesia.dirty\u write/1
    :Mnesia.dirty\u read/2

我已经花了好几个小时浏览这些文档,但没有任何东西可以作为加快速度的潜在途径——因此我可能会盯着性能墙,但如果有人能澄清/确认/建议,我将不胜感激。

简短回答:

[
    { :ram_copies, [node()] },
    { :local_content, true },
    { :attributes, [:key,:value] }
]
尽管Mnesia使用ETS作为非持久性数据存储(ram_复制表)的引擎,但Mnesia检查所选表是否已复制或是否具有索引的开销使其在写入新记录方面比ETS慢

发件人:

[
    { :ram_copies, [node()] },
    { :local_content, true },
    { :attributes, [:key,:value] }
]
对于非持久性数据库存储,首选Ets表而不是Mnesia local_内容表。与Ets写入操作相比,即使是Mnesia dirty_写入操作也会带来固定的开销。Mnesia必须检查该表是否已复制或具有索引,这涉及到对每个脏_写入至少进行一次Ets查找。因此,Ets写入总是比Mnesia写入快

但是,你可以考虑<代码> MNESIA:ETS/2 受益于你的MSNISA表上ETS的性能:

mnesia:ets(Fun, [, Args]) -> ResultOfFun | exit(Reason)
发件人:

[
    { :ram_copies, [node()] },
    { :local_content, true },
    { :attributes, [:key,:value] }
]
mnesia:ets/2
在未受事务保护的原始上下文中调用乐趣。Mnesia函数调用在Fun中执行,并直接在本地ets表上执行,前提是本地存储类型为ram_拷贝,且表不会复制到其他节点。订阅不会触发,检查点也不会更新,但速度非常快。如果所有操作均为只读,则此功能也可应用于光盘拷贝表。有关详细信息,请参阅mnesia:activity/4和用户指南


Edit:我编写了一个基准测试并在我的机器上运行,以澄清
mnesia:ets/1
mnesia:dirty\u write/1
ets:insert/2
之间的大致区别

mnesia_ets(Limit) ->
    application:ensure_started(mnesia),
    mnesia:create_table(foo, [{ram_copies, [node()]}]),
    WriteFun = fun() -> 
        [mnesia:write({foo, I, I}) || I <- lists:seq(1, Limit)]
    end,
    timer:tc(fun() -> mnesia:ets(fun() -> WriteFun() end) end).

ets(Limit) ->
    ets:new(bar, [named_table, public]),
    WriteFun = fun() -> 
        [ets:insert(bar, {bar, I, I}) || I <- lists:seq(1, Limit)]
    end,
    timer:tc(fun() -> WriteFun() end).

mnesia(Limit) ->
    application:ensure_started(mnesia),
    mnesia:create_table(baz, [{ram_copies, [node()]}]),
    WriteFun = fun() -> 
        [mnesia:dirty_write({baz, I, I}) || I <- lists:seq(1, Limit)]
    end,
    timer:tc(fun() -> WriteFun() end).
mnesia_ets(限制)->
应用:确保启动(mnesia),
mnesia:create_table(foo,[{ram_copies,[node()]}]),
WriteFun=fun()->
[mnesia:write({foo,I,I})| I mnesia:ets(fun()->WriteFun()end)end)。
电子交易系统(限额)->
ets:新(条形图,[命名表,公共]),
WriteFun=fun()->
[ets:insert(bar,{bar,I,I})| | I WriteFun()结束)。
记忆障碍(限制)->
应用:确保启动(mnesia),
mnesia:create_表(baz,[{ram_copies,[node()]}]),
WriteFun=fun()->
[mnesia:dirty_write({baz,I,I})| | I WriteFun()结束)。
写入
10000000
记录的结果如下:

  • ets:insert/2的4303992微秒
  • 对于
    mnesia:ets/1
  • 29798736微秒用于
    mnesia:dirty_write/1

因此,基于上述原因,我可以得出结论,
mnesia:ets/1
mnesia:dirty_write/1
快,但仍然比
ets:insert/2

慢。正如哈米德雷扎·索莱曼尼(Hamidreza Soleimani)指出的那样,mnesia总是比ets慢,这在大多数情况下都不是问题有可能。我不知道它对你的情况是否有帮助,但它总是值得一看

mnesia_ets(Limit) ->
    application:ensure_started(mnesia),
    mnesia:create_table(foo, [{ram_copies, [node()]}]),
    WriteFun = fun() -> 
        [mnesia:write({foo, I, I}) || I <- lists:seq(1, Limit)]
    end,
    timer:tc(fun() -> mnesia:ets(fun() -> WriteFun() end) end).

ets(Limit) ->
    ets:new(bar, [named_table, public]),
    WriteFun = fun() -> 
        [ets:insert(bar, {bar, I, I}) || I <- lists:seq(1, Limit)]
    end,
    timer:tc(fun() -> WriteFun() end).

mnesia(Limit) ->
    application:ensure_started(mnesia),
    mnesia:create_table(baz, [{ram_copies, [node()]}]),
    WriteFun = fun() -> 
        [mnesia:dirty_write({baz, I, I}) || I <- lists:seq(1, Limit)]
    end,
    timer:tc(fun() -> WriteFun() end).
Erlang Factory的这张幻灯片介绍了一种为mnesia实现自定义备份的方法。与ETS相比,它可能(也可能不)允许您跳过减慢mnesia速度的检查


我看到了关于:mnesia.ets的事情,你能提供一个例子吗?我不太明白它在函数-mnesia调用中想要什么?@zackehh一些mnesia函数是上下文敏感的,比如
mnesia:write/1
。所以如果你把它包装在
fun
中,并将函数传递给
mnesia:ets/1
,它将直接执行仅在本地ets表上使用,没有此类开销。例如:
mnesia:ets(fun()->mnesia:write({table_name,key_1,val_1})end)
。明白了,试了,慢一点:p谢谢你的建议,但我想打开上下文和使用上下文节省的费用一样昂贵。哦,好吧!顺便说一下,我不能在
mnesia:ets/2
中使用
mnesia:dirty\u write/1
-只有
mnesia:dirty\u write/1
?有趣的是,我复制了你的基准测试,并看到了类似的结果.看来Benchfella在骗我!我看到的吞吐量几乎超过了被削减时间的50%,这对我来说已经足够好了(我正在通过GenServer,所以比现在写要浪费更多的时间)。谢谢!