File 1538-logger_olp-Avoid-repeated-calls-to-persistent_term-p.patch of Package erlang
From effc59c059aaac7b960635a36d27ef4fdb614a8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muska=C5=82a?= <michal@muskala.eu>
Date: Sat, 29 Jun 2024 11:17:37 +0100
Subject: [PATCH] [logger_olp] Avoid repeated calls to persistent_term:put
`logger_otp` would call back to `persistent_term:put` on each iteration even when the mode wouldn't actually change. Even though `persistent_term:put` guards against changing value to the same avoiding the most expensive operations, it still aquires some locks and does potentially other fairly expensive work. We can avoid this with a simple check in `logger_olp` to try and update the value only if it has actually changed.
---
lib/kernel/src/logger_olp.erl | 44 ++++++++++++++++++-----------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/lib/kernel/src/logger_olp.erl b/lib/kernel/src/logger_olp.erl
index bbfe32800e..20b12a5d08 100644
--- a/lib/kernel/src/logger_olp.erl
+++ b/lib/kernel/src/logger_olp.erl
@@ -174,7 +174,7 @@ init([Name,Module,Args,Options]) ->
put(olp_ref,OlpRef),
try Module:init(Args) of
{ok,CBState} ->
- set_mode(ModeRef, async),
+ set_mode(ModeRef, async, undefined),
T0 = ?timestamp(),
proc_lib:init_ack({ok,self(),OlpRef}),
%% Storing options in state to avoid copying
@@ -261,11 +261,11 @@ handle_cast(Msg, #{module:=Module, cb_state:=CBState} = State) ->
{stop, Reason, State#{cb_state=>CBState1}}
end.
-handle_info(timeout, #{mode_ref:=ModeRef} = State) ->
+handle_info(timeout, #{mode_ref:=ModeRef,mode:=Mode} = State) ->
State1 = notify(idle,State),
- State2 = maybe_notify_mode_change(async,State1),
+ State2 = maybe_notify_mode_change(async,Mode,State1),
{noreply, State2#{idle => true,
- mode => set_mode(ModeRef, async),
+ mode => set_mode(ModeRef, async, Mode),
burst_msg_count => 0}};
handle_info(Msg, #{module := Module, cb_state := CBState} = State) ->
case try_callback_call(Module,handle_info,[Msg, CBState]) of
@@ -344,7 +344,7 @@ do_load(Msg, CallOrCast, State) ->
%% this function is called by do_load/3 after an overload check
%% has been performed, where QLen > FlushQLen
-flush(T1, State=#{id := _Name, last_load_ts := _T0, mode_ref := ModeRef}) ->
+flush(T1, State=#{id := _Name, last_load_ts := _T0, mode_ref := ModeRef, mode := Mode}) ->
%% flush load messages in the mailbox (a limited number in order
%% to not cause long delays)
NewFlushed = flush_load(?FLUSH_MAX_N),
@@ -363,9 +363,9 @@ flush(T1, State=#{id := _Name, last_load_ts := _T0, mode_ref := ModeRef}) ->
State2 = ?update_max_time(?diff_time(T1,_T0),State1),
State3 = ?update_max_qlen(QLen1,State2),
- State4 = maybe_notify_mode_change(async,State3),
+ State4 = maybe_notify_mode_change(async,Mode,State3),
{dropped,?update_other(flushed,FLUSHED,NewFlushed,
- State4#{mode => set_mode(ModeRef,async),
+ State4#{mode => set_mode(ModeRef,async,Mode),
last_qlen => QLen1,
last_load_ts => T1})}.
@@ -494,16 +494,16 @@ check_load(State = #{id:=_Name, mode_ref := ModeRef, mode := Mode,
%% be dropped on the client side (never sent to
%% the olp process).
IncDrops = if Mode == drop -> 0; true -> 1 end,
- {set_mode(ModeRef, drop), IncDrops,0};
+ {set_mode(ModeRef, drop, Mode), IncDrops,0};
QLen >= SyncModeQLen ->
- {set_mode(ModeRef, sync), 0,0};
+ {set_mode(ModeRef, sync, Mode), 0,0};
true ->
- {set_mode(ModeRef, async), 0,0}
+ {set_mode(ModeRef, async, Mode), 0,0}
end,
State1 = ?update_other(drops,DROPS,_NewDrops,State),
State2 = ?update_max_qlen(QLen,State1),
State3 = ?update_max_mem(Mem,State2),
- State4 = maybe_notify_mode_change(Mode1,State3),
+ State4 = maybe_notify_mode_change(Mode1,Mode,State3),
{Mode1, QLen, Mem,
?update_other(flushes,FLUSHES,_NewFlushes,
State4#{last_qlen => QLen})}.
@@ -594,16 +594,18 @@ overload_levels_ok(Options) ->
get_mode(Ref) -> persistent_term:get(Ref, async).
-set_mode(Ref, M) ->
- true = is_atom(M), persistent_term:put(Ref, M), M.
-
-maybe_notify_mode_change(drop,#{mode:=Mode0}=State)
- when Mode0=/=drop ->
- notify({mode_change,Mode0,drop},State);
-maybe_notify_mode_change(Mode1,#{mode:=drop}=State)
- when Mode1==async; Mode1==sync ->
- notify({mode_change,drop,Mode1},State);
-maybe_notify_mode_change(_,State) ->
+set_mode(_Ref, NewMode, OldMode) when NewMode =:= OldMode -> NewMode;
+set_mode(Ref, NewMode, _OldMode) when is_atom(NewMode) ->
+ persistent_term:put(Ref, NewMode),
+ NewMode.
+
+maybe_notify_mode_change(drop,OldMode,State)
+ when OldMode=/=drop ->
+ notify({mode_change,OldMode,drop},State);
+maybe_notify_mode_change(NewMode,drop,State)
+ when NewMode==async; NewMode==sync ->
+ notify({mode_change,drop,NewMode},State);
+maybe_notify_mode_change(_,_,State) ->
State.
notify(Note,#{module:=Module,cb_state:=CBState}=State) ->
--
2.35.3