File 4601-stdlib-timer-better-resolution-control.patch of Package erlang

From a2265b5d9ccbdf866be5eaf583eaf683e19d4893 Mon Sep 17 00:00:00 2001
From: jdamanalo <jamanalo5@up.edu.ph>
Date: Thu, 24 Nov 2022 21:01:26 +0800
Subject: [PATCH 1/2] stdlib/timer: better resolution control - added a final
 `erlang:time_unit()` argument to `tc/[1,2,3]`

Tackles #3264. Primarily for systems with worse resolution than a microsecond.
---
 lib/stdlib/doc/src/timer.xml           | 41 ++++++++++++++++-----
 lib/stdlib/src/timer.erl               | 50 ++++++++++++++++++++------
 lib/stdlib/test/timer_simple_SUITE.erl | 13 +++++++
 3 files changed, 85 insertions(+), 19 deletions(-)

diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index 2cbf7977a9..6f3aef8c7e 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -319,14 +319,37 @@
 
     <func>
       <name name="tc" arity="1" since="OTP R14B03"/>
-      <name name="tc" arity="2" since="OTP R14B"/>
-      <name name="tc" arity="3" since=""/>
+      <name name="tc" arity="2" clause_i="1" since="OTP R14B"/>
+      <name name="tc" arity="3" clause_i="1" since=""/>
+      <fsummary>Measure the real time it takes to evaluate <c>Fun</c>.</fsummary>
+      <desc>
+        <taglist>
+          <tag><c>tc/3</c></tag>
+          <item>
+            <p>Calls function <c>timer:tc(Module, Function, Arguments, microsecond)</c>.</p>
+          </item>
+          <tag><c>tc/2</c></tag>
+          <item>
+            <p>Calls function <c>timer:tc(Fun, Arguments, microsecond)</c>.</p>
+          </item>
+          <tag><c>tc/1</c></tag>
+          <item>
+            <p>Calls function <c>timer:tc(Fun, microsecond)</c>.</p>
+          </item>
+        </taglist>
+      </desc>
+    </func>
+
+    <func>
+      <name name="tc" arity="2" clause_i="2" since=""/>
+      <name name="tc" arity="3" clause_i="2" since=""/>
+      <name name="tc" arity="4" since=""/>
       <fsummary>Measure the real time it takes to evaluate <c>apply(Module,
         Function, Arguments)</c> or <c>apply(Fun, Arguments)</c>.</fsummary>
-      <type_desc variable="Time">In microseconds</type_desc>
+      <type_desc variable="Time">In the specified <c>TimeUnit</c></type_desc>
       <desc>
         <taglist>
-          <tag><c>tc/3</c></tag>
+          <tag><c>tc/4</c></tag>
           <item>
             <p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
               <anno>Arguments</anno>)</c> and measures the elapsed real time as 
@@ -334,18 +357,18 @@
               <c>erlang:monotonic_time/0</c></seemfa>.</p>
             <p>Returns <c>{<anno>Time</anno>, <anno>Value</anno>}</c>, where
               <c><anno>Time</anno></c> is the elapsed real time in
-              <em>microseconds</em>, and <c><anno>Value</anno></c> is what is
+              the specified <c>TimeUnit</c>, and <c><anno>Value</anno></c> is what is
               returned from the apply.</p>
           </item>
-          <tag><c>tc/2</c></tag>
+          <tag><c>tc/3</c></tag>
           <item>
             <p>Evaluates <c>apply(<anno>Fun</anno>, <anno>Arguments</anno>)</c>.
-              Otherwise the same as <c>tc/3</c>.</p>
+              Otherwise the same as <c>tc/4</c>.</p>
           </item>
-          <tag><c>tc/1</c></tag>
+          <tag><c>tc/2</c></tag>
           <item>
             <p>Evaluates <c><anno>Fun</anno>()</c>. Otherwise the same as
-              <c>tc/2</c>.</p>
+              <c>tc/3</c>.</p>
           </item>
         </taglist>
       </desc>
diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl
index 780ae4c7f1..17c12f2931 100644
--- a/lib/stdlib/src/timer.erl
+++ b/lib/stdlib/src/timer.erl
@@ -24,7 +24,7 @@
          exit_after/3, exit_after/2, kill_after/2, kill_after/1,
          apply_interval/4, apply_repeatedly/4,
          send_interval/3, send_interval/2,
-         cancel/1, sleep/1, tc/1, tc/2, tc/3, now_diff/2,
+         cancel/1, sleep/1, tc/1, tc/2, tc/3, tc/4, now_diff/2,
          seconds/1, minutes/1, hours/1, hms/3]).
 
 -export([start_link/0, start/0,
@@ -247,41 +247,71 @@ sleep(T) ->
                    Time :: integer(),
                    Value :: term().
 tc(F) ->
+    tc(F, microsecond).
+
+%%
+%% Measure the execution time (in microseconds) for Fun(Args)
+%%      or the execution time (in TimeUnit) for Fun().
+%%
+-spec tc(Fun, Arguments) -> {Time, Value}
+              when Fun :: function(),
+                   Arguments :: [term()],
+                   Time :: integer(),
+                   Value :: term();
+        (Fun, TimeUnit) -> {Time, Value}
+              when Fun :: function(),
+                   TimeUnit :: erlang:time_unit(),
+                   Time :: integer(),
+                   Value :: term().
+tc(F, A) when is_list(A) ->
+    tc(F, A, microsecond);
+tc(F, TimeUnit) ->
     T1 = erlang:monotonic_time(),
     Val = F(),
     T2 = erlang:monotonic_time(),
-    Time = erlang:convert_time_unit(T2 - T1, native, microsecond),
+    Time = erlang:convert_time_unit(T2 - T1, native, TimeUnit),
     {Time, Val}.
 
 %%
-%% Measure the execution time (in microseconds) for Fun(Args).
+%% Measure the execution time (in microseconds) for an MFA
+%%      or the execution time (in TimeUnit) for Fun(Args).
 %%
--spec tc(Fun, Arguments) -> {Time, Value}
+-spec tc(Module, Function, Arguments) -> {Time, Value}
+              when Module :: module(),
+                   Function :: atom(),
+                   Arguments :: [term()],
+                   Time :: integer(),
+                   Value :: term();
+        (Fun, Arguments, TimeUnit) -> {Time, Value}
               when Fun :: function(),
                    Arguments :: [term()],
+                   TimeUnit :: erlang:time_unit(),
                    Time :: integer(),
                    Value :: term().
-tc(F, A) ->
+tc(M, F, A) when is_list(A) ->
+    tc(M, F, A, microsecond);
+tc(F, A, TimeUnit) ->
     T1 = erlang:monotonic_time(),
     Val = apply(F, A),
     T2 = erlang:monotonic_time(),
-    Time = erlang:convert_time_unit(T2 - T1, native, microsecond),
+    Time = erlang:convert_time_unit(T2 - T1, native, TimeUnit),
     {Time, Val}.
 
 %%
-%% Measure the execution time (in microseconds) for an MFA.
+%% Measure the execution time (in TimeUnit) for an MFA.
 %%
--spec tc(Module, Function, Arguments) -> {Time, Value}
+-spec tc(Module, Function, Arguments, TimeUnit) -> {Time, Value}
               when Module :: module(),
                    Function :: atom(),
                    Arguments :: [term()],
+                   TimeUnit :: erlang:time_unit(),
                    Time :: integer(),
                    Value :: term().
-tc(M, F, A) ->
+tc(M, F, A, TimeUnit) ->
     T1 = erlang:monotonic_time(),
     Val = apply(M, F, A),
     T2 = erlang:monotonic_time(),
-    Time = erlang:convert_time_unit(T2 - T1, native, microsecond),
+    Time = erlang:convert_time_unit(T2 - T1, native, TimeUnit),
     {Time, Val}.
 
 %%
diff --git a/lib/stdlib/test/timer_simple_SUITE.erl b/lib/stdlib/test/timer_simple_SUITE.erl
index 9031a2d242..761689dc51 100644
--- a/lib/stdlib/test/timer_simple_SUITE.erl
+++ b/lib/stdlib/test/timer_simple_SUITE.erl
@@ -731,7 +731,19 @@ tc(Config) when is_list(Config) ->
              true -> ok
          end,
 
+    %% tc/4
+    {Res4, ok} = timer:tc(timer, sleep, [500], millisecond),
+    ok = if
+             Res4 < 500 -> {too_early, Res4};
+             Res4 > 800 -> {too_late, Res4};
+             true -> ok
+         end,
+
     %% Check that timer:tc don't catch errors
+    ok = try timer:tc(erlang, exit, [foo], second)
+         catch exit:foo -> ok
+         end,
+
     ok = try timer:tc(erlang, exit, [foo])
          catch exit:foo -> ok
          end,
@@ -746,6 +758,7 @@ tc(Config) when is_list(Config) ->
 
     %% Check that return values are propageted
     Self = self(),
+    {_, Self} = timer:tc(erlang, self, [], second),
     {_, Self} = timer:tc(erlang, self, []),
     {_, Self} = timer:tc(fun(P) -> P end, [self()]),
     {_, Self} = timer:tc(fun() -> self() end),
-- 
2.35.3

openSUSE Build Service is sponsored by