aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSiri Hansen <[email protected]>2013-02-26 11:05:51 +0100
committerSiri Hansen <[email protected]>2013-03-04 11:05:33 +0100
commit999e827ed1d9b5c966af2fc7480e57d2b60b7b09 (patch)
tree1e4b6fbfdeb7eed4074661c75566f13946c31e96
parent0756a6676d465862056a0fb0969eee827f1a844d (diff)
downloadotp-999e827ed1d9b5c966af2fc7480e57d2b60b7b09.tar.gz
otp-999e827ed1d9b5c966af2fc7480e57d2b60b7b09.tar.bz2
otp-999e827ed1d9b5c966af2fc7480e57d2b60b7b09.zip
[observer] Improve measurement of CPU utilization in etop
Now using scheduler_wall_time instead of runtime/wall_clock to get cpu utilization. The old version could give CPU utilization far beyond 100%. Also, a bug which sometimes gave a badarith when calculating the CPU utilization is corrected.
-rw-r--r--lib/observer/src/etop.erl35
-rw-r--r--lib/runtime_tools/include/observer_backend.hrl23
-rw-r--r--lib/runtime_tools/src/observer_backend.erl30
3 files changed, 70 insertions, 18 deletions
diff --git a/lib/observer/src/etop.erl b/lib/observer/src/etop.erl
index 428757e5ce..2610060eae 100644
--- a/lib/observer/src/etop.erl
+++ b/lib/observer/src/etop.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2013. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -325,13 +325,40 @@ loadinfo(SysI) ->
#etop_info{n_procs = Procs,
run_queue = RQ,
now = Now,
- wall_clock = {_, WC},
- runtime = {_, RT}} = SysI,
- Cpu = round(100*RT/WC),
+ wall_clock = WC,
+ runtime = RT} = SysI,
+ Cpu = calculate_cpu_utilization(WC,RT),
Clock = io_lib:format("~2.2.0w:~2.2.0w:~2.2.0w",
tuple_to_list(element(2,calendar:now_to_datetime(Now)))),
{Cpu,Procs,RQ,Clock}.
+calculate_cpu_utilization({_,WC},{_,RT}) ->
+ %% Old version of observer_backend, using statistics(wall_clock)
+ %% and statistics(runtime)
+ case {WC,RT} of
+ {0,0} ->
+ 0;
+ {0,_} ->
+ 100;
+ _ ->
+ round(100*RT/WC)
+ end;
+calculate_cpu_utilization(_,undefined) ->
+ %% First time collecting - no cpu utilization has been measured
+ %% since scheduler_wall_time flag is not yet on
+ 0;
+calculate_cpu_utilization(_,RTInfo) ->
+ %% New version of observer_backend, using statistics(scheduler_wall_time)
+ Sum = lists:foldl(fun({_,A,T},{AAcc,TAcc}) -> {A+AAcc,T+TAcc} end,
+ {0,0},
+ RTInfo),
+ case Sum of
+ {0,0} ->
+ 0;
+ {Active,Total} ->
+ round(100*Active/Total)
+ end.
+
meminfo(MemI, [Tag|Tags]) ->
[round(get_mem(Tag, MemI)/1024)|meminfo(MemI, Tags)];
meminfo(_MemI, []) -> [].
diff --git a/lib/runtime_tools/include/observer_backend.hrl b/lib/runtime_tools/include/observer_backend.hrl
index 4be9baca5b..91647a4468 100644
--- a/lib/runtime_tools/include/observer_backend.hrl
+++ b/lib/runtime_tools/include/observer_backend.hrl
@@ -1,26 +1,27 @@
-%% ``The contents of this file are subject to the Erlang Public License,
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
-%% retrieved via the world wide web at http://www.erlang.org/.
-%%
+%% retrieved online at http://www.erlang.org/.
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
-%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
-%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
-%% AB. All Rights Reserved.''
-%%
-%% $Id$
+%%
+%% %CopyrightEnd%
%%
-record(etop_info,
{now = {0, 0, 0},
n_procs = 0,
- wall_clock = {0, 0},
- runtime = {0, 0},
+ wall_clock,
+ runtime,
run_queue = 0,
alloc_areas = [],
memi = [{total, 0},
diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl
index e8c9b50c33..d1d291d5cb 100644
--- a/lib/runtime_tools/src/observer_backend.erl
+++ b/lib/runtime_tools/src/observer_backend.erl
@@ -217,15 +217,39 @@ fetch_stats_loop(Parent, Time) ->
%% etop backend
%%
etop_collect(Collector) ->
+ %% If this is the first time and the scheduler_wall_time flag is
+ %% false, SchedulerWallTime will be 'undefined' (and show 0 cpu
+ %% utilization in etop). Next time the flag will be true and then
+ %% there will be a measurement.
+ SchedulerWallTime = erlang:statistics(scheduler_wall_time),
+
+ %% Turn off the flag while collecting data per process etc.
+ case erlang:system_flag(scheduler_wall_time,false) of
+ false ->
+ %% First time and the flag was false - start a monitoring
+ %% process to set the flag back to false when etop is stopped.
+ spawn(fun() -> flag_holder_proc(Collector) end);
+ _ ->
+ ok
+ end,
+
ProcInfo = etop_collect(processes(), []),
+
Collector ! {self(),#etop_info{now = now(),
n_procs = length(ProcInfo),
run_queue = erlang:statistics(run_queue),
- wall_clock = erlang:statistics(wall_clock),
- runtime = erlang:statistics(runtime),
+ runtime = SchedulerWallTime,
memi = etop_memi(),
procinfo = ProcInfo
- }}.
+ }},
+ erlang:system_flag(scheduler_wall_time,true).
+
+flag_holder_proc(Collector) ->
+ Ref = erlang:monitor(process,Collector),
+ receive
+ {'DOWN',Ref,_,_,_} ->
+ erlang:system_flag(scheduler_wall_time,false)
+ end.
etop_memi() ->
try