在 Elixir/Erlang 的(本地)Mnesia 实例上实现最佳写入性能
Achieving the best write performance on a (local) Mnesia instance in Elixir/Erlang
简短而甜美;我正在构建一个新项目,我 可以 使用 ETS,但我更愿意使用 Mnesia 支持 - 由于内置 t运行sactions 之类的东西可能派上用场。我不关心复制和扩展到其他节点,这就是为什么我认为 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 的读取性能相当,但写入性能要慢得多。我想知道是否有任何方法可以加快速度(例如关闭复制检查等)。
附加信息:
健忘症Table:
[
{ :ram_copies, [node()] },
{ :local_content, true },
{ :attributes, [:key,:value] }
]
测试
- ETS 操作使用
:ets.lookup/2
和 :ets.insert/2
- Mnesia 操作使用
:mnesia.dirty_write/1
和 :mnesia.dirty_read/2
我已经搜索了几个小时的文档,但没有发现任何可以加快速度的潜在方法 - 所以我可能正在盯着性能墙,但如果有人可以 clarify/confirm/suggest,它'不胜感激。
简答:
尽管 Mnesia 使用 ETS 作为非持久数据存储的引擎(ram_copies tables)但是 Mnesia 用于检查所选 table 是否被复制或具有索引的开销使其在写入新记录时比 ETS 慢。
For non-persistent database storage, prefer Ets tables over Mnesia local_content tables. Even the Mnesia dirty_write operations carry a fixed overhead compared to Ets writes. Mnesia must check if the table is replicated or has indices, this involves at least one Ets lookup for each dirty_write. Thus, Ets writes is always faster than Mnesia writes.
但是您可以考虑 mnesia:ets/2
从 ETS 在您的 Mnesia tables 上的性能中受益:
mnesia:ets(Fun, [, Args]) -> ResultOfFun | exit(Reason)
来自 Documentation:
mnesia:ets/2
calls the Fun in a raw context that is not protected by a transaction. The Mnesia function call is performed in the Fun and performed directly on the local ets tables on the assumption that the local storage type is ram_copies and the tables are not replicated to other nodes. Subscriptions are not triggered and checkpoints are not updated, but it is extremely fast. This function can also be applied to disc_copies tables if all operations are read only. For details, see mnesia:activity/4 and the User's Guide.
编辑: 我在我的机器上写了一个基准测试 运行 来阐明 mnesia:ets/1
、mnesia:dirty_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).
写入10000000
条记录的结果如下:
- 4303992 微秒
ets:insert/2
- 15911681 微秒
mnesia:ets/1
- 29798736 微秒
mnesia:dirty_write/1
所以我可以得出结论,由于上述原因,mnesia:ets/1
比 mnesia:dirty_write/1
快,但它仍然比 ets:insert/2
慢。
正如 Hamidreza Soleimani 所指出的,Mnesia 总是比 ETS 慢,这在大多数情况下都不是问题。只是想指出另一种可能性。我不知道它对你的情况是否有帮助,但它总是值得一看。
Erlang Factory 的这张幻灯片介绍了一种实现自定义支持 mnesia 的方法。与 ETS 相比,它可能(或可能不会)允许您跳过减慢 Mnesia 速度的检查。
http://www.erlang-factory.com/static/upload/media/143415340626199euc2015mnesialeveldb.pdf
简短而甜美;我正在构建一个新项目,我 可以 使用 ETS,但我更愿意使用 Mnesia 支持 - 由于内置 t运行sactions 之类的东西可能派上用场。我不关心复制和扩展到其他节点,这就是为什么我认为 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 的读取性能相当,但写入性能要慢得多。我想知道是否有任何方法可以加快速度(例如关闭复制检查等)。
附加信息:
健忘症Table:
[
{ :ram_copies, [node()] },
{ :local_content, true },
{ :attributes, [:key,:value] }
]
测试
- ETS 操作使用
:ets.lookup/2
和:ets.insert/2
- Mnesia 操作使用
:mnesia.dirty_write/1
和:mnesia.dirty_read/2
我已经搜索了几个小时的文档,但没有发现任何可以加快速度的潜在方法 - 所以我可能正在盯着性能墙,但如果有人可以 clarify/confirm/suggest,它'不胜感激。
简答:
尽管 Mnesia 使用 ETS 作为非持久数据存储的引擎(ram_copies tables)但是 Mnesia 用于检查所选 table 是否被复制或具有索引的开销使其在写入新记录时比 ETS 慢。
For non-persistent database storage, prefer Ets tables over Mnesia local_content tables. Even the Mnesia dirty_write operations carry a fixed overhead compared to Ets writes. Mnesia must check if the table is replicated or has indices, this involves at least one Ets lookup for each dirty_write. Thus, Ets writes is always faster than Mnesia writes.
但是您可以考虑 mnesia:ets/2
从 ETS 在您的 Mnesia tables 上的性能中受益:
mnesia:ets(Fun, [, Args]) -> ResultOfFun | exit(Reason)
来自 Documentation:
mnesia:ets/2
calls the Fun in a raw context that is not protected by a transaction. The Mnesia function call is performed in the Fun and performed directly on the local ets tables on the assumption that the local storage type is ram_copies and the tables are not replicated to other nodes. Subscriptions are not triggered and checkpoints are not updated, but it is extremely fast. This function can also be applied to disc_copies tables if all operations are read only. For details, see mnesia:activity/4 and the User's Guide.
编辑: 我在我的机器上写了一个基准测试 运行 来阐明 mnesia:ets/1
、mnesia:dirty_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).
写入10000000
条记录的结果如下:
- 4303992 微秒
ets:insert/2
- 15911681 微秒
mnesia:ets/1
- 29798736 微秒
mnesia:dirty_write/1
所以我可以得出结论,由于上述原因,mnesia:ets/1
比 mnesia:dirty_write/1
快,但它仍然比 ets:insert/2
慢。
正如 Hamidreza Soleimani 所指出的,Mnesia 总是比 ETS 慢,这在大多数情况下都不是问题。只是想指出另一种可能性。我不知道它对你的情况是否有帮助,但它总是值得一看。
Erlang Factory 的这张幻灯片介绍了一种实现自定义支持 mnesia 的方法。与 ETS 相比,它可能(或可能不会)允许您跳过减慢 Mnesia 速度的检查。
http://www.erlang-factory.com/static/upload/media/143415340626199euc2015mnesialeveldb.pdf