summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorjdamanalo <jamanalo5@up.edu.ph>2022-11-24 21:01:26 +0800
committerjdamanalo <jamanalo5@up.edu.ph>2022-11-28 14:19:00 +0800
commita2265b5d9ccbdf866be5eaf583eaf683e19d4893 (patch)
tree1789269fc1fc8c72c2d379ad1eac1fd5baa77b2d /lib
parentd713e274781b2e344c7f8e7bbc064281d71eeefc (diff)
downloaderlang-a2265b5d9ccbdf866be5eaf583eaf683e19d4893.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/stdlib/doc/src/timer.xml41
-rw-r--r--lib/stdlib/src/timer.erl50
-rw-r--r--lib/stdlib/test/timer_simple_SUITE.erl13
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),