Skip to content

Use new OTP 26 fun ets:lookup_element/4 #9809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 6 additions & 15 deletions deps/rabbit/src/rabbit_db_binding.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1117,8 +1117,8 @@ route_in_mnesia_v1(SrcName, [_|_] = RoutingKeys) ->
%% ets:select/2 is expensive because it needs to compile the match spec every
%% time and lookup does not happen by a hash key.
%%
%% In contrast, route_v2/2 increases end-to-end message sending throughput
%% (i.e. from RabbitMQ client to the queue process) by up to 35% by using ets:lookup_element/3.
%% In contrast, route_v2/3 increases end-to-end message sending throughput
%% (i.e. from RabbitMQ client to the queue process) by up to 35% by using ets:lookup_element/4.
%% Only the direct exchange type uses the rabbit_index_route table to store its
%% bindings by table key tuple {SourceExchange, RoutingKey}.
-spec route_v2(ets:table(), rabbit_types:binding_source(), [rabbit_router:routing_key(), ...]) ->
Expand All @@ -1132,16 +1132,7 @@ route_v2(Table, SrcName, [_|_] = RoutingKeys) ->
end, RoutingKeys).

destinations(Table, SrcName, RoutingKey) ->
%% Prefer try-catch block over checking Key existence with ets:member/2.
%% The latter reduces throughput by a few thousand messages per second because
%% of function db_member_hash in file erl_db_hash.c.
%% We optimise for the happy path, that is the binding / table key is present.
try
ets:lookup_element(Table,
{SrcName, RoutingKey},
#index_route.destination)
catch
error:badarg ->
[]
end.

ets:lookup_element(Table,
{SrcName, RoutingKey},
#index_route.destination,
[]).
7 changes: 1 addition & 6 deletions deps/rabbit/src/rabbit_exchange_type_direct.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,7 @@ route(#exchange{name = Name, type = Type}, Msg) ->

route(#exchange{name = Name, type = Type}, Msg, _Opts) ->
Routes = mc:get_annotation(routing_keys, Msg),
case Type of
direct ->
rabbit_db_binding:match_routing_key(Name, Routes, true);
_ ->
rabbit_db_binding:match_routing_key(Name, Routes, false)
end.
rabbit_db_binding:match_routing_key(Name, Routes, Type =:= direct).

validate(_X) -> ok.
validate_binding(_X, _B) -> ok.
Expand Down
20 changes: 6 additions & 14 deletions deps/rabbit/src/rabbit_quorum_queue.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ cluster_state(Name) ->
case whereis(Name) of
undefined -> down;
_ ->
case ets_lookup_element(ra_state, Name, 2, undefined) of
case ets:lookup_element(ra_state, Name, 2, undefined) of
recover ->
recovering;
_ ->
Expand Down Expand Up @@ -1496,10 +1496,10 @@ i(messages, Q) when ?is_amqqueue(Q) ->
quorum_messages(QName);
i(messages_ready, Q) when ?is_amqqueue(Q) ->
QName = amqqueue:get_name(Q),
ets_lookup_element(queue_coarse_metrics, QName, 2, 0);
ets:lookup_element(queue_coarse_metrics, QName, 2, 0);
i(messages_unacknowledged, Q) when ?is_amqqueue(Q) ->
QName = amqqueue:get_name(Q),
ets_lookup_element(queue_coarse_metrics, QName, 3, 0);
ets:lookup_element(queue_coarse_metrics, QName, 3, 0);
i(policy, Q) ->
case rabbit_policy:name(Q) of
none -> '';
Expand All @@ -1517,7 +1517,7 @@ i(effective_policy_definition, Q) ->
end;
i(consumers, Q) when ?is_amqqueue(Q) ->
QName = amqqueue:get_name(Q),
Consumers = ets_lookup_element(queue_metrics, QName, 2, []),
Consumers = ets:lookup_element(queue_metrics, QName, 2, []),
proplists:get_value(consumers, Consumers, 0);
i(memory, Q) when ?is_amqqueue(Q) ->
{Name, _} = amqqueue:get_pid(Q),
Expand All @@ -1539,7 +1539,7 @@ i(state, Q) when ?is_amqqueue(Q) ->
end;
i(local_state, Q) when ?is_amqqueue(Q) ->
{Name, _} = amqqueue:get_pid(Q),
ets_lookup_element(ra_state, Name, 2, not_member);
ets:lookup_element(ra_state, Name, 2, not_member);
i(garbage_collection, Q) when ?is_amqqueue(Q) ->
{Name, _} = amqqueue:get_pid(Q),
try
Expand Down Expand Up @@ -1683,7 +1683,7 @@ is_process_alive(Name, Node) ->
-spec quorum_messages(rabbit_amqqueue:name()) -> non_neg_integer().

quorum_messages(QName) ->
ets_lookup_element(queue_coarse_metrics, QName, 4, 0).
ets:lookup_element(queue_coarse_metrics, QName, 4, 0).

quorum_ctag(Int) when is_integer(Int) ->
integer_to_binary(Int);
Expand Down Expand Up @@ -1796,14 +1796,6 @@ notify_decorators(QName, F, A) ->
ok
end.

ets_lookup_element(Tbl, Key, Pos, Default) ->
try ets:lookup_element(Tbl, Key, Pos) of
V -> V
catch
_:badarg ->
Default
end.

erpc_call(Node, M, F, A, _Timeout)
when Node =:= node() ->
%% Only timeout 'infinity' optimises the local call in OTP 23-25 avoiding a new process being spawned:
Expand Down
7 changes: 3 additions & 4 deletions deps/rabbitmq_management_agent/src/rabbit_mgmt_data.erl
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,11 @@ match_consumer_spec(Id) ->
match_queue_consumer_spec(Id) ->
[{{{'$1', '_', '_'}, '_'}, [{'==', {Id}, '$1'}], ['$_']}].

lookup_element(Table, Key) -> lookup_element(Table, Key, 2).
lookup_element(Table, Key) ->
lookup_element(Table, Key, 2).

lookup_element(Table, Key, Pos) ->
try ets:lookup_element(Table, Key, Pos)
catch error:badarg -> []
end.
ets:lookup_element(Table, Key, Pos, []).

-spec lookup_smaller_sample(atom(), any()) -> maybe_slide().
lookup_smaller_sample(Table, Id) ->
Expand Down