File 5551-Optimize-application-get_key-to-avoid-full-record-co.patch of Package erlang

From 393253064b6592033fd846614bf365eb85434c0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muska=C5=82a?= <micmus@fb.com>
Date: Tue, 23 Jan 2024 12:56:14 +0000
Subject: [PATCH] Optimize application:get_key to avoid full record copies

`application:get_key` would previously copy from ETS the entire appl
record and then select a single field from it. This can be optimized
to only select the specific field that's required with `ets:match`.

Especially for `application:get_key(X, env)` this would copy the
appl record, completely discard it and lookup the environment
which is stored separately. We still need to query separately
to preserve the behaviour of returning `undefined` for unloaded
applications.
---
 lib/kernel/src/application_controller.erl | 75 ++++++++++++-----------
 1 file changed, 40 insertions(+), 35 deletions(-)

diff --git a/lib/kernel/src/application_controller.erl b/lib/kernel/src/application_controller.erl
index 60080c155e..57f4f9ab89 100644
--- a/lib/kernel/src/application_controller.erl
+++ b/lib/kernel/src/application_controller.erl
@@ -372,42 +372,47 @@ get_pid_key(Master, Key) ->
 	_ -> undefined
     end.
 
-get_key(AppName, Key) ->
-    case ets:lookup(ac_tab, {loaded, AppName}) of
-	[{_, Appl}] ->
-	    case Key of 
-		description ->
-		    {ok, Appl#appl.descr};
-		id ->
-		    {ok, Appl#appl.id};
-		vsn ->
-		    {ok, Appl#appl.vsn};
-		modules ->
-		    {ok, (Appl#appl.appl_data)#appl_data.mods};
-		maxP ->
-		    {ok, (Appl#appl.appl_data)#appl_data.maxP};
-		maxT ->
-		    {ok, (Appl#appl.appl_data)#appl_data.maxT};
-		registered ->
-		    {ok, (Appl#appl.appl_data)#appl_data.regs};
-		included_applications ->
-		    {ok, Appl#appl.inc_apps};
-                optional_applications ->
-                    {ok, Appl#appl.opt_apps};
-		applications ->
-		    {ok, Appl#appl.apps};
-		env ->
-		    {ok, get_all_env(AppName)};
-		mod ->
-		    {ok, (Appl#appl.appl_data)#appl_data.mod};
-		start_phases ->
-		    {ok, (Appl#appl.appl_data)#appl_data.phases};
-		_ -> undefined
-	    end;
-	_ ->
-	    undefined
+get_key(AppName, description) ->
+    get_key_direct(AppName, #appl{descr = '$1', _ = '_'});
+get_key(AppName, id) ->
+    get_key_direct(AppName, #appl{id = '$1', _ = '_'});
+get_key(AppName, vsn) ->
+    get_key_direct(AppName, #appl{vsn = '$1', _ = '_'});
+get_key(AppName, modules) ->
+    get_key_data(AppName, #appl_data{mods = '$1', _ = '_'});
+get_key(AppName, maxP) ->
+    get_key_data(AppName, #appl_data{maxP = '$1', _ = '_'});
+get_key(AppName, maxT) ->
+    get_key_data(AppName, #appl_data{maxT = '$1', _ = '_'});
+get_key(AppName, registered) ->
+    get_key_data(AppName, #appl_data{regs = '$1', _ = '_'});
+get_key(AppName, included_applications) ->
+    get_key_direct(AppName, #appl{inc_apps = '$1', _ = '_'});
+get_key(AppName, optional_applications) ->
+    get_key_direct(AppName, #appl{opt_apps = '$1', _ = '_'});
+get_key(AppName, applications) ->
+    get_key_direct(AppName, #appl{apps = '$1', _ = '_'});
+get_key(AppName, env) ->
+    case ets:member(ac_tab, {loaded, AppName}) of
+        true -> {ok, get_all_env(AppName)};
+        false -> undefined
+    end;
+get_key(AppName, mod) ->
+    get_key_data(AppName, #appl_data{mod = '$1', _ = '_'});
+get_key(AppName, start_phases) ->
+    get_key_data(AppName, #appl_data{phases = '$1', _ = '_'});
+get_key(_, _) ->
+    undefined.
+
+get_key_direct(AppName, Match) ->
+    case ets:match(ac_tab, {{loaded, AppName}, Match}) of
+        [[Value]] -> {ok, Value};
+        [] -> undefined
     end.
-	    
+
+get_key_data(AppName, Match) ->
+	get_key_direct(AppName, #appl{appl_data = Match, _ = '_'}).
+
 get_pid_all_key(Master) ->
     case ets:match(ac_tab, {{application_master, '$1'}, Master}) of
 	[[AppName]] -> get_all_key(AppName);
-- 
2.35.3

openSUSE Build Service is sponsored by