Skip to content

Commit cae5868

Browse files
committed
perf: add rpc exec worker pool
1 parent 189139d commit cae5868

5 files changed

Lines changed: 146 additions & 8 deletions

File tree

.github/workflows/run_test_case.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
run: |
2020
make test
2121
22-
- uses: actions/upload-artifact@v1
22+
- uses: actions/upload-artifact@v4
2323
if: always()
2424
with:
2525
name: logs

src/gen_rpc_acceptor.erl

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -340,13 +340,8 @@ handle_cast(M, F, A, Ordered, #state{socket=Socket, driver=Driver, peer=Peer, co
340340
?log(debug, "event=request_not_allowed driver=~s socket=\"~s\" control=~s method=cast module=~s",[Driver, gen_rpc_helper:socket_to_string(Socket), Control, RealM])
341341
end.
342342

343-
exec_cast(M, F, A, _PreserveOrder = true) ->
344-
{Pid, MRef} = erlang:spawn_monitor(M, F, A),
345-
receive
346-
{'DOWN', MRef, process, Pid, _} -> ok
347-
end;
348-
exec_cast(M, F, A, _PreserveOrder = false) ->
349-
_ = erlang:spawn(M, F, A),
343+
exec_cast(M, F, A, PreserveOrder) ->
344+
ok = gen_rpc_exec_worker_sup:submit(M, F, A, PreserveOrder),
350345
ok.
351346

352347
reply_immediately(Payload, #state{driver_mod = DriverMod, driver = Driver, socket = Socket}) ->

src/gen_rpc_exec_worker.erl

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
%%% -*-mode:erlang;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*-
2+
%%% ex: set ft=erlang fenc=utf-8 sts=4 ts=4 sw=4 et:
3+
4+
-module(gen_rpc_exec_worker).
5+
6+
%%% Behaviour
7+
-behaviour(gen_server).
8+
9+
-include("logger.hrl").
10+
11+
%%% API
12+
-export([start_link/1, worker_name/1]).
13+
14+
%%% gen_server callbacks
15+
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
16+
17+
%%% ===================================================
18+
%%% API
19+
%%% ===================================================
20+
-spec start_link(pos_integer()) -> gen_server:startlink_ret().
21+
start_link(Index) when is_integer(Index), Index > 0 ->
22+
gen_server:start_link({via, gen_rpc_registry, worker_name(Index)}, ?MODULE, Index, []).
23+
24+
-spec worker_name(pos_integer()) -> {exec_cast_worker, pos_integer()}.
25+
worker_name(Index) when is_integer(Index), Index > 0 ->
26+
{exec_cast_worker, Index}.
27+
28+
%%% ===================================================
29+
%%% gen_server callbacks
30+
%%% ===================================================
31+
init(Index) ->
32+
{ok, Index}.
33+
34+
handle_call(_Request, _From, State) ->
35+
{reply, {error, unsupported_call}, State}.
36+
37+
handle_cast({exec_cast, M, F, A}, State) ->
38+
execute_cast(M, F, A),
39+
{noreply, State};
40+
handle_cast(_Request, State) ->
41+
{noreply, State}.
42+
43+
handle_info(_Info, State) ->
44+
{noreply, State}.
45+
46+
terminate(_Reason, _State) ->
47+
ok.
48+
49+
code_change(_OldVsn, State, _Extra) ->
50+
{ok, State}.
51+
52+
%%% ===================================================
53+
%%% Internal functions
54+
%%% ===================================================
55+
execute_cast(M, F, A) ->
56+
try erlang:apply(M, F, A) of
57+
_Result ->
58+
ok
59+
catch
60+
Class:Reason:Stacktrace ->
61+
?log(error,
62+
"event=exec_cast_failed module=~p function=~p args=\"~0p\" class=~p reason=\"~0p\" stacktrace=\"~0p\"",
63+
[M, F, A, Class, Reason, Stacktrace]),
64+
ok
65+
end.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
%%% -*-mode:erlang;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*-
2+
%%% ex: set ft=erlang fenc=utf-8 sts=4 ts=4 sw=4 et:
3+
4+
-module(gen_rpc_exec_worker_sup).
5+
6+
%%% Behaviour
7+
-behaviour(supervisor).
8+
9+
-include("logger.hrl").
10+
11+
%%% API
12+
-export([start_link/0, submit/4]).
13+
14+
%%% Supervisor callbacks
15+
-export([init/1]).
16+
17+
-define(FIRST_WORKER_INDEX, 1).
18+
19+
%%% ===================================================
20+
%%% API
21+
%%% ===================================================
22+
-spec start_link() -> supervisor:startlink_ret().
23+
start_link() ->
24+
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
25+
26+
-spec submit(module(), atom(), list(), boolean()) -> ok.
27+
submit(M, F, A, PreserveOrder) ->
28+
Name = gen_rpc_exec_worker:worker_name(worker_index(PreserveOrder)),
29+
case gen_rpc_registry:whereis_name(Name) of
30+
undefined ->
31+
?log(notice, "event=exec_cast_worker_unavailable, name=~p", [Name]),
32+
exec_cast(M, F, A, PreserveOrder);
33+
Pid ->
34+
gen_server:cast(Pid, {exec_cast, M, F, A}),
35+
ok
36+
end.
37+
38+
%%% ===================================================
39+
%%% Supervisor callbacks
40+
%%% ===================================================
41+
init([]) ->
42+
Children = [worker_spec(Index) || Index <- lists:seq(1, worker_count())],
43+
{ok, {{one_for_one, 15, 1}, Children}}.
44+
45+
%%% ===================================================
46+
%%% Internal functions
47+
%%% ===================================================
48+
%%% The `exec_cast/4` function is a fallback that executes the cast directly if the worker is unavailable.
49+
%%% Usually happens when relup failed to start the worker pool.
50+
exec_cast(M, F, A, _PreserveOrder = true) ->
51+
{Pid, MRef} = erlang:spawn_monitor(M, F, A),
52+
receive
53+
{'DOWN', MRef, process, Pid, _} -> ok
54+
end;
55+
exec_cast(M, F, A, _PreserveOrder = false) ->
56+
_ = erlang:spawn(M, F, A),
57+
ok.
58+
59+
worker_spec(Index) ->
60+
Name = gen_rpc_exec_worker:worker_name(Index),
61+
{Name, {gen_rpc_exec_worker, start_link, [Index]}, permanent, 5000, worker, [gen_rpc_exec_worker]}.
62+
63+
worker_count() ->
64+
erlang:system_info(schedulers).
65+
66+
worker_index(true) ->
67+
?FIRST_WORKER_INDEX;
68+
worker_index(false) ->
69+
random_worker_index().
70+
71+
random_worker_index() ->
72+
case worker_count() of
73+
1 ->
74+
1;
75+
Count ->
76+
erlang:phash2(make_ref(), Count) + 1
77+
end.

src/supervisor/gen_rpc_sup.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ start_link() ->
2929
init([]) ->
3030
{ok, {{one_for_one, 100, 1}, [
3131
{gen_rpc_registry, {gen_rpc_registry, start_link, []}, permanent, 5000, worker, [gen_rpc_registry]},
32+
{gen_rpc_exec_worker_sup, {gen_rpc_exec_worker_sup, start_link, []}, permanent, 5000, supervisor, [gen_rpc_exec_worker_sup]},
3233
{gen_rpc_server_tcp, {gen_rpc_server,start_link,[tcp]}, permanent, 5000, worker, [gen_rpc_server]},
3334
{gen_rpc_server_ssl, {gen_rpc_server,start_link,[ssl]}, permanent, 5000, worker, [gen_rpc_server]},
3435
{gen_rpc_acceptor_sup, {gen_rpc_acceptor_sup,start_link, []}, permanent, 5000, supervisor, [gen_rpc_acceptor_sup]},

0 commit comments

Comments
 (0)