Skip to content

Commit 3d8a364

Browse files
committed
Avoid list allocation of lists:filter/2
In the common case no MA entries need to removed. This commit saves a list allocation for the common case. (When reading from a stream, x-exchange or x-routing-key should make `lists:all/2` return immediately because these two message annotations will be prepended before writing to the stream.)
1 parent e550aeb commit 3d8a364

1 file changed

Lines changed: 44 additions & 39 deletions

File tree

deps/rabbit/src/mc_amqp.erl

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -472,45 +472,50 @@ convert_from_3_13_msg(#msg{header = H,
472472

473473
-spec protocol_state_message_annotations(amqp_annotations(), mc:annotations()) ->
474474
amqp_annotations().
475-
protocol_state_message_annotations(MA0, Anns) ->
476-
%% filter all MA's that are going to be overwritten by ANNS
477-
MA = lists:filter(
478-
fun
479-
({{symbol, <<"x-exchange">>}, _}) ->
480-
not maps:is_key(?ANN_EXCHANGE, Anns);
481-
({{symbol, <<"x-routing-key">>}, _}) ->
482-
not maps:is_key(?ANN_ROUTING_KEYS, Anns);
483-
({{symbol, <<"x-opt-rabbitmq-received-time">>}, _}) ->
484-
not maps:is_key(<<"timestamp_in_ms">>, Anns);
485-
({{symbol, <<"x-opt-deaths">>}, _}) ->
486-
not maps:is_key(deaths, Anns);
487-
({{symbol, <<"x-", _/binary>> = K}, _}) ->
488-
not maps:is_key(K, Anns);
489-
(_) ->
490-
true
491-
end, MA0),
492-
493-
maps:fold(
494-
fun(?ANN_EXCHANGE, Exchange, L) ->
495-
[{{symbol, <<"x-exchange">>}, {utf8, Exchange}} | L];
496-
(?ANN_ROUTING_KEYS, RKeys, L) ->
497-
RKey = hd(RKeys),
498-
[{{symbol, <<"x-routing-key">>}, {utf8, RKey}} | L];
499-
(<<"x-", _/binary>> = K, V, L)
500-
when V =/= undefined ->
501-
%% any x-* annotations get added as message annotations
502-
[{{symbol, K}, mc_util:infer_type(V)} | L];
503-
(<<"timestamp_in_ms">>, V, L) ->
504-
[{{symbol, <<"x-opt-rabbitmq-received-time">>},
505-
{timestamp, V}} | L];
506-
(deaths, Deaths, L)
507-
when is_list(Deaths) ->
508-
Maps = encode_deaths(Deaths),
509-
[{{symbol, <<"x-opt-deaths">>},
510-
{array, map, Maps}} | L];
511-
(_, _, Acc) ->
512-
Acc
513-
end, MA, Anns).
475+
protocol_state_message_annotations(MA, Anns) ->
476+
%% To efficiently overwrite MA with Anns, we first remove entries in MA
477+
%% that will be re-added by Anns. We optimise for the common case where no
478+
%% MA entries need to be removed.
479+
Fun = fun({{symbol, <<"x-exchange">>}, _}) ->
480+
not maps:is_key(?ANN_EXCHANGE, Anns);
481+
({{symbol, <<"x-routing-key">>}, _}) ->
482+
not maps:is_key(?ANN_ROUTING_KEYS, Anns);
483+
({{symbol, <<"x-opt-rabbitmq-received-time">>}, _}) ->
484+
not maps:is_key(<<"timestamp_in_ms">>, Anns);
485+
({{symbol, <<"x-opt-deaths">>}, _}) ->
486+
not maps:is_key(deaths, Anns);
487+
({{symbol, <<"x-", _/binary>> = K}, _}) ->
488+
not maps:is_key(K, Anns);
489+
(_) ->
490+
true
491+
end,
492+
MA1 = case lists:all(Fun, MA) of
493+
true ->
494+
MA;
495+
false ->
496+
lists:filter(Fun, MA)
497+
end,
498+
499+
maps:fold(fun(?ANN_EXCHANGE, Exchange, L) ->
500+
[{{symbol, <<"x-exchange">>}, {utf8, Exchange}} | L];
501+
(?ANN_ROUTING_KEYS, RKeys, L) ->
502+
RKey = hd(RKeys),
503+
[{{symbol, <<"x-routing-key">>}, {utf8, RKey}} | L];
504+
(<<"x-", _/binary>> = K, V, L)
505+
when V =/= undefined ->
506+
%% any x-* annotations get added as message annotations
507+
[{{symbol, K}, mc_util:infer_type(V)} | L];
508+
(<<"timestamp_in_ms">>, V, L) ->
509+
[{{symbol, <<"x-opt-rabbitmq-received-time">>},
510+
{timestamp, V}} | L];
511+
(deaths, Deaths, L)
512+
when is_list(Deaths) ->
513+
Maps = encode_deaths(Deaths),
514+
[{{symbol, <<"x-opt-deaths">>},
515+
{array, map, Maps}} | L];
516+
(_, _, Acc) ->
517+
Acc
518+
end, MA1, Anns).
514519

515520
encode(Sections) when is_list(Sections) ->
516521
[amqp10_framing:encode_bin(Section) || Section <- Sections,

0 commit comments

Comments
 (0)