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

openSUSE Build Service is sponsored by