From 4bfccba1943a21b1f723607f5b8e25773e48d98d Mon Sep 17 00:00:00 2001
From: Anders Svensson <anders@erlang.org>
Date: Fri, 28 Apr 2017 08:59:31 +0200
Subject: Avoid recreating records

This old construction is approximately two to four times slower from
best (no elements modified) to worst (all modified) case, with the new
construction having constant speed.
---
 lib/diameter/src/base/diameter_lib.erl     | 31 ------------------------------
 lib/diameter/src/base/diameter_traffic.erl | 18 +++++++++++++----
 2 files changed, 14 insertions(+), 35 deletions(-)

(limited to 'lib')

diff --git a/lib/diameter/src/base/diameter_lib.erl b/lib/diameter/src/base/diameter_lib.erl
index 3928769b5e..58b9a29812 100644
--- a/lib/diameter/src/base/diameter_lib.erl
+++ b/lib/diameter/src/base/diameter_lib.erl
@@ -37,7 +37,6 @@
          ipaddr/1,
          spawn_opts/2,
          wait/1,
-         fold_tuple/3,
          fold_n/3,
          for_n/2,
          log/4]).
@@ -340,36 +339,6 @@ down(MRef)
   when is_reference(MRef) ->
     receive {'DOWN', MRef, process, _, _} = T -> T end.
 
-%% ---------------------------------------------------------------------------
-%% # fold_tuple/3
-%% ---------------------------------------------------------------------------
-
--spec fold_tuple(N, T0, T)
-   -> tuple()
- when N  :: pos_integer(),
-      T0 :: tuple(),
-      T  :: tuple()
-          | undefined.
-
-%% Replace fields in T0 by those of T starting at index N, unless the
-%% new value is 'undefined'.
-%%
-%% eg. fold_tuple(2, Hdr, #diameter_header{end_to_end_id = 42})
-
-fold_tuple(_, T, undefined) ->
-    T;
-
-fold_tuple(N, T0, T1) ->
-    {_, T} = lists:foldl(fun(V, {I,_} = IT) -> {I+1, ft(V, IT)} end,
-                         {N, T0},
-                         lists:nthtail(N-1, tuple_to_list(T1))),
-    T.
-
-ft(undefined, {_, T}) ->
-    T;
-ft(Value, {Idx, T}) ->
-    setelement(Idx, T, Value).
-
 %% ---------------------------------------------------------------------------
 %% # fold_n/3
 %% ---------------------------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 4a5df722e7..72fb92dcf9 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -1438,11 +1438,21 @@ make_retransmit_header(Hdr) ->
     Hdr#diameter_header{is_retransmitted = true}.
 
 %% fold_record/2
+%%
+%% Replace elements in the first record by those in the second that
+%% differ from undefined.
+
+fold_record(Rec0, undefined) ->
+    Rec0;
+fold_record(Rec0, Rec) ->
+    list_to_tuple(fold(tuple_to_list(Rec0), tuple_to_list(Rec))).
 
-fold_record(undefined, R) ->
-    R;
-fold_record(Rec, R) ->
-    diameter_lib:fold_tuple(2, Rec, R).
+fold([], []) ->
+    [];
+fold([H | T0], [undefined | T]) ->
+    [H | fold(T0, T)];
+fold([_ | T0], [H | T]) ->
+    [H | fold(T0, T)].
 
 %% send_R/6
 
-- 
cgit v1.2.3