Skip to content

Instantly share code, notes, and snippets.

@cooldaemon
Created March 31, 2012 16:28
Show Gist options
  • Save cooldaemon/2266553 to your computer and use it in GitHub Desktop.
Save cooldaemon/2266553 to your computer and use it in GitHub Desktop.
Process vs ETS vs Mnesia
-module(process_vs_ets_vs_mnesia).
-author('cooldaemon@gmail.com').
-export([run/3]).
-record(store, {key, value}).
run(TryCount, ProcessCount, ReadCount) ->
Pids = lists:map(
fun (_) -> spawn_link(fun reader_process/0) end,
lists:seq(1, ProcessCount)
),
mnesia:start(),
do(TryCount, Pids, ReadCount),
mnesia:stop(),
lists:foreach(fun (Pid) -> Pid ! finish end, Pids).
reader_process() ->
receive
{run, Count, Function, ReturnPid} ->
lists:foreach(fun (_) -> Function() end, lists:seq(1, Count)),
ReturnPid ! {self(), ok};
finish ->
exit(normal);
Other ->
io:fwrite("Reader received unknown message: ~p~n", [Other])
end,
reader_process().
do(0, _, _) -> ok;
do(TryCount, ReaderPids, ReadCount) ->
io:fwrite("--<reduction:~p>--~n", [TryCount]),
lists:foreach(
fun ({F, TargetName}) ->
{ok, [RunTime, WallClock]} = F(ReaderPids, ReadCount),
io:fwrite("~s: ~p(~p)ms~n", [TargetName, RunTime, WallClock])
end,
[
{fun process/2, "process"},
{fun ets/2, "ets"},
{fun mnesia/2, "mnesia"},
{fun mnesia_dirty/2, "mnesia_dirty"}
]
),
do(TryCount-1, ReaderPids, ReadCount).
run_reader(Pids, Count, Function) ->
lists:foreach(fun (Pid) ->
Pid ! {run, Count, Function, self()}
end, Pids),
lists:foreach(fun (Pid) ->
receive {Pid, _} -> ok end
end, Pids),
ok.
benchmark(TargetFunction) ->
lists:foreach(fun statistics/1, [runtime, wall_clock]),
Result = TargetFunction(),
Times = lists:map(
fun (Type) -> {_, T} = statistics(Type), T end,
[runtime, wall_clock]
),
{Result, Times}.
process(ReaderPids, ReadCount) ->
DBPid = spawn_link(fun db_process/0),
Result = benchmark(fun () ->
run_reader(ReaderPids, ReadCount, fun () ->
DBPid ! {get, foo, self()},
receive {ok, bar} -> ok end
end)
end),
DBPid ! finish,
Result.
db_process() ->
receive
{get, foo, ReturnPid} ->
ReturnPid ! {ok, bar};
finish ->
exit(normal);
Other ->
io:fwrite("Received unknown message: ~p~n", [Other])
end,
db_process().
ets(ReaderPids, ReadCount) ->
Ets = ets:new(store, [set, public]),
ets:insert(Ets, {foo, bar}),
benchmark(fun () ->
run_reader(ReaderPids, ReadCount, fun () ->
[{foo, bar}] = ets:lookup(Ets, foo)
end)
end).
mnesia(ReaderPids, ReadCount) ->
ok = init_mnesia(),
benchmark(fun () ->
run_reader(ReaderPids, ReadCount, fun () ->
[{store, foo, bar}] = mnesia:activity(
async_dirty,
fun mnesia:read/2,
[store, foo]
)
end)
end).
mnesia_dirty(ReaderPids, ReadCount) ->
ok = init_mnesia(),
benchmark(fun () ->
run_reader(ReaderPids, ReadCount, fun () ->
[{store, foo, bar}] = mnesia:dirty_read(store, foo)
end)
end).
init_mnesia() ->
mnesia:delete_table(store),
{atomic, ok} = mnesia:create_table(
store,
[
{record_name, store},
{type, set},
{attributes, record_info(fields, store)}
]
),
mnesia:activity(
async_dirty,
fun mnesia:write/1,
[#store{key = foo, value = bar}]
).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment