File 2452-Avoid-setting-meta-options-if-possible.patch of Package erlang

From 36c2431c9f86b14e365e573834d5eb758bac6a05 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Wed, 20 Dec 2023 17:22:19 +0100
Subject: [PATCH 02/14] Avoid setting meta options if possible

---
 lib/kernel/src/gen_tcp_socket.erl | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/lib/kernel/src/gen_tcp_socket.erl b/lib/kernel/src/gen_tcp_socket.erl
index 54b1fe6f73..255443680d 100644
--- a/lib/kernel/src/gen_tcp_socket.erl
+++ b/lib/kernel/src/gen_tcp_socket.erl
@@ -1425,6 +1425,9 @@ server_opts() ->
 -compile({inline, [meta/1]}).
 meta(D) -> maps:with(maps:keys(server_write_opts()), D).
 
+-compile({inline, [meta_opts/0]}).
+meta_opts() -> maps:keys(server_write_opts()).
+
 
 %%% ========================================================================
 %%% State Machine
@@ -1789,19 +1792,29 @@ handle_event({call, From}, {getopts, Opts}, State, {P, D}) ->
 %% Call: setopts/1
 handle_event({call, From}, {setopts, Opts}, State, {P, D}) ->
     %% ?DBG([{setopts, Opts}, {state, State}, {d, D}]),
-    {Result_1, D_1} = state_setopts(P, D, State, Opts),
-    %% ?DBG([{result, Result_1}, {d1, D_1}]),
+    %%
+    %% Optimize option setting by finding out which options that changes
+    %%
+    %% Work on a minimal D map and see what changes
+    {Result_1, D_1} =
+        state_setopts(P, maps:with([active,recv_httph], D), State, Opts),
+    D_2 = maps:merge(maps:remove(recv_httph, D), D_1),
+    %% ?DBG([{result, Result_1}, {d1, D_2}]),
+    case is_map_keys(meta_opts(), D_1) of
+        true -> % Metadata option change - rewrite
+            ok = socket:setopt(P#params.socket, {otp,meta}, meta(D_2));
+        false ->
+            ok
+    end,
     Result =
         case Result_1 of
             {error, enoprotoopt} ->
                 %% If we get this error, the options is not valid for
                 %% this (tcp) protocol.
-                _ = socket:setopt(P#params.socket, {otp,meta}, meta(D_1)),
                 {error, einval};
 
             {error, {invalid, _}} ->
                 %% If we get this error, the options where crap.
-                _ = socket:setopt(P#params.socket, {otp,meta}, meta(D_1)),
                 {error, einval};
 
             {error, einval} ->
@@ -1809,15 +1822,13 @@ handle_event({call, From}, {setopts, Opts}, State, {P, D}) ->
                 %% the socket is in a "bad state" (maybe its closed).
                 %% So, if that is the case we accept that we may not be
                 %% able to update the meta data.
-                _ = socket:setopt(P#params.socket, {otp,meta}, meta(D_1)),
                 Result_1;
             _ ->
                 %% We should really handle this better. stop_and_reply?
-                ok = socket:setopt(P#params.socket, {otp,meta}, meta(D_1)),
                 Result_1
         end,
     Reply = {reply, From, Result},
-    handle_active(P, D_1, State, [Reply]);
+    handle_active(P, D_2, State, [Reply]);
 
 %% Call: setopt_active/1
 handle_event({call, From}, {setopt_active, Active}, State, {P, D}) ->
@@ -3520,6 +3531,11 @@ reverse_improper([], Acc) -> Acc;
 reverse_improper(T, Acc) -> [T | Acc].
 
 
+is_map_keys([], #{}) -> false;
+is_map_keys([Key|Keys], Map) ->
+    is_map_key(Key, Map) orelse is_map_keys(Keys, Map).
+
+
 %% -------------------------------------------------------------------------
 -ifdef(undefined).
 
-- 
2.35.3

openSUSE Build Service is sponsored by