From 0756a6676d465862056a0fb0969eee827f1a844d Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 26 Feb 2013 10:56:36 +0100 Subject: [observer] Fix non tail-recusive loop when measuring scheduler utilization --- lib/runtime_tools/src/observer_backend.erl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/runtime_tools/src/observer_backend.erl b/lib/runtime_tools/src/observer_backend.erl index 9498412505..e8c9b50c33 100644 --- a/lib/runtime_tools/src/observer_backend.erl +++ b/lib/runtime_tools/src/observer_backend.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 @@ -199,20 +199,19 @@ get_table_list(mnesia, Opts) -> lists:foldl(Info, [], mnesia:system_info(tables)). fetch_stats(Parent, Time) -> - erlang:system_flag(scheduler_wall_time, true), process_flag(trap_exit, true), - fetch_stats_loop(Parent, Time), - erlang:system_flag(scheduler_wall_time, false). + fetch_stats_loop(Parent, Time). fetch_stats_loop(Parent, Time) -> + erlang:system_flag(scheduler_wall_time, true), receive - _Msg -> normal + _Msg -> erlang:system_flag(scheduler_wall_time, false) after Time -> _M = Parent ! {stats, 1, erlang:statistics(scheduler_wall_time), erlang:statistics(io), erlang:memory()}, - fetch_stats(Parent, Time) + fetch_stats_loop(Parent, Time) end. %% %% etop backend -- cgit v1.2.3 From 999e827ed1d9b5c966af2fc7480e57d2b60b7b09 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 26 Feb 2013 11:05:51 +0100 Subject: [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. --- lib/observer/src/etop.erl | 35 +++++++++++++++++++++++--- lib/runtime_tools/include/observer_backend.hrl | 23 +++++++++-------- lib/runtime_tools/src/observer_backend.erl | 30 +++++++++++++++++++--- 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 -- cgit v1.2.3 From f6177aea6270909574e7fc0598d4f16c764491f5 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 26 Feb 2013 12:00:53 +0100 Subject: [observer] Accept current function for a process to be 'undefined' on hipe --- lib/observer/src/etop_gui.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/observer/src/etop_gui.erl b/lib/observer/src/etop_gui.erl index f5cc0deb38..3971646abc 100644 --- a/lib/observer/src/etop_gui.erl +++ b/lib/observer/src/etop_gui.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 @@ -276,7 +276,12 @@ clear_lines(From, To, Grid) -> end. formatmfa({M, F, A}) -> - io_lib:format("~w:~w/~w",[M, F, A]). + io_lib:format("~w:~w/~w",[M, F, A]); +formatmfa(Other) -> + %% E.g. when running hipe - the current_function for some + %% processes will be 'undefined' + io_lib:format("~w",[Other]). + makegridlines([#etop_proc_info{pid=Pid, mem=Mem, -- cgit v1.2.3 From 4469c7d0cb3ba5d3c404ebd13097072d8b531091 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 26 Feb 2013 15:31:47 +0100 Subject: [observer] Kill slave node between tests in etop_SUITE To avoid that the second test case fails (due to duplicate name) if the first fails - always kill the slave node after each test case. --- lib/observer/test/etop_SUITE.erl | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/observer/test/etop_SUITE.erl b/lib/observer/test/etop_SUITE.erl index 06577f82cc..6ce3ea59cf 100644 --- a/lib/observer/test/etop_SUITE.erl +++ b/lib/observer/test/etop_SUITE.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 @@ -21,7 +21,8 @@ %% Test functions -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2,text/1,text_tracing_off/1]). + init_per_group/2,end_per_group/2]). +-export([text/1,text/2,text_tracing_off/1,text_tracing_off/2]). -export([init_per_testcase/2, end_per_testcase/2]). -include_lib("test_server/include/test_server.hrl"). @@ -31,7 +32,10 @@ init_per_testcase(_Case, Config) -> ?line Dog=test_server:timetrap(?default_timeout), [{watchdog, Dog}|Config]. -end_per_testcase(_Case, Config) -> +end_per_testcase(Case, Config) -> + try apply(?MODULE,Case,[cleanup,Config]) + catch error:undef -> ok + end, Dog=?config(watchdog, Config), ?t:timetrap_cancel(Dog), ok. @@ -82,9 +86,12 @@ text() -> ?line timer:sleep(3000), ?line etop:config(sort,msg_q), ?line timer:sleep(3000), - ?line etop:stop(), - ?line ?t:stop_node(Node), ok. +text(cleanup,_Config) -> + etop:stop(), + {ok,Host} = inet:gethostname(), + Node = list_to_atom("node2@"++Host), + ?t:stop_node(Node). text_tracing_off(suite) -> []; @@ -111,7 +118,10 @@ text_tracing_off(Config) when is_list(Config) -> ?line timer:sleep(3000), ?line etop:config(sort,runtime), % this should not crash, but has no effect ?line timer:sleep(3000), - ?line etop:stop(), - ?line ?t:stop_node(Node), ok. +text_tracing_off(cleanup,_Config) -> + etop:stop(), + {ok,Host} = inet:gethostname(), + Node = list_to_atom("node2@"++Host), + ?t:stop_node(Node). -- cgit v1.2.3 From 6ab4b1c2a7a5a89dd8ea4094bd7fb4c23745acfc Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 26 Feb 2013 15:36:52 +0100 Subject: [observer] Extend timer to allow trace msgs to arrive over tcp/ip Some tests fail (mostly on windows) every now and then with too few trace messages in log. Extending the timer from 200 to 500 ms to see if this is the reason. Plus removing a compiler warning in ttb_SUITE. --- lib/observer/test/ttb_SUITE.erl | 5 +++-- lib/observer/test/ttb_helper.erl | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl index 695d41b48a..f3fcd9f283 100644 --- a/lib/observer/test/ttb_SUITE.erl +++ b/lib/observer/test/ttb_SUITE.erl @@ -1,7 +1,8 @@ +%% %% %CopyrightBegin% %% %% -%% Copyright Ericsson AB 2002-2010. 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 @@ -57,7 +58,7 @@ init_per_testcase(Case, Config) -> catch error:undef -> ok end, [{watchdog, Dog}|Config]. -end_per_testcase(Case, Config) -> +end_per_testcase(_Case, Config) -> %% try apply(?MODULE,Case,[cleanup,Config]) %% catch error:undef -> ok %% end, diff --git a/lib/observer/test/ttb_helper.erl b/lib/observer/test/ttb_helper.erl index 76b06cd3ce..05f6d73aef 100644 --- a/lib/observer/test/ttb_helper.erl +++ b/lib/observer/test/ttb_helper.erl @@ -70,7 +70,7 @@ msgs(N) -> msgs_ip(N) -> [c(client, put, [test_msg]) || _ <- lists:seq(1, N)], s(server, received, [a,b]), - timer:sleep(200). %% allow trace messages to arrive over tcp/ip + timer:sleep(500). %% allow trace messages to arrive over tcp/ip run() -> ttb({local, "A"}), -- cgit v1.2.3