perf(router): receive-mark optimise for short-lived transaction process

This commit is contained in:
Zaiming Shi 2021-05-04 14:58:32 +02:00 committed by Zaiming (Stone) Shi
parent e44bd431b9
commit 92d3e16d43
1 changed files with 28 additions and 18 deletions

View File

@ -266,28 +266,38 @@ maybe_trans(Fun, Args) ->
end, []) end, [])
end. end.
%% The created fun only terminates with explicit exception
-dialyzer({nowarn_function, [trans/2]}).
-spec(trans(function(), list(any())) -> ok | {error, term()}). -spec(trans(function(), list(any())) -> ok | {error, term()}).
trans(Fun, Args) -> trans(Fun, Args) ->
%% trigger selective receive optimization of compiler, {WPid, RefMon} =
%% ideal for handling bursty traffic. spawn_monitor(
Ref = erlang:make_ref(), %% NOTE: this is under the assumption that crashes in Fun
Owner = self(), %% are caught by mnesia:transaction/2.
{WPid, RefMon} = spawn_monitor( %% Future changes should keep in mind that this process
fun() -> %% always exit with database write result.
Res = case mnesia:transaction(Fun, Args) of fun() ->
{atomic, Ok} -> Ok; Res = case mnesia:transaction(Fun, Args) of
{aborted, Reason} -> {error, Reason} {atomic, Ok} -> Ok;
end, {aborted, Reason} -> {error, Reason}
Owner ! {Ref, Res} end,
end), exit({shutdown, Res})
end),
%% Receive a 'shutdown' exit to pass result from the short-lived process.
%% so the receive below can be receive-mark optimized by the compiler.
%%
%% If the result is sent as a regular message, we'll have to
%% either demonitor (with flush which is essentially a 'receive' since
%% the process is no longer alive after the result has been received),
%% or use a plain 'receive' to drain the normal 'DOWN' message.
%% However the compiler does not optimize this second 'receive'.
receive receive
{Ref, TransRes} ->
receive
{'DOWN', RefMon, process, WPid, normal} -> ok
end,
TransRes;
{'DOWN', RefMon, process, WPid, Info} -> {'DOWN', RefMon, process, WPid, Info} ->
{error, {trans_crash, Info}} case Info of
{shutdown, Result} -> Result;
_ -> {error, {trans_crash, Info}}
end
end. end.
lock_router() -> lock_router() ->