diff options
Diffstat (limited to 'lib/percept/src/percept_analyzer.erl')
-rw-r--r-- | lib/percept/src/percept_analyzer.erl | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/lib/percept/src/percept_analyzer.erl b/lib/percept/src/percept_analyzer.erl deleted file mode 100644 index f38d026905..0000000000 --- a/lib/percept/src/percept_analyzer.erl +++ /dev/null @@ -1,368 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% - -%% @doc Utility functions to operate on percept data. These functions should -%% be considered experimental. Behaviour may change in future releases. - --module(percept_analyzer). --export([ - minmax/1, - waiting_activities/1, - activities2count/2, - activities2count/3, - activities2count2/2, - analyze_activities/2, - runnable_count/1, - runnable_count/2, - seconds2ts/2, - minmax_activities/2, - mean/1 - ]). - --include("percept.hrl"). - -%%========================================================================== -%% -%% Interface functions -%% -%%========================================================================== - - -%% @spec minmax([{X, Y}]) -> {MinX, MinY, MaxX, MaxY} -%% X = number() -%% Y = number() -%% MinX = number() -%% MinY = number() -%% MaxX = number() -%% MaxY = number() -%% @doc Returns the min and max of a set of 2-dimensional numbers. - -minmax(Data) -> - Xs = [ X || {X,_Y} <- Data], - Ys = [ Y || {_X, Y} <- Data], - {lists:min(Xs), lists:min(Ys), lists:max(Xs), lists:max(Ys)}. - -%% @spec mean([number()]) -> {Mean, StdDev, N} -%% Mean = float() -%% StdDev = float() -%% N = integer() -%% @doc Calculates the mean and the standard deviation of a set of -%% numbers. - -mean([]) -> {0, 0, 0}; -mean([Value]) -> {Value, 0, 1}; -mean(List) -> mean(List, {0, 0, 0}). - -mean([], {Sum, SumSquare, N}) -> - Mean = Sum / N, - StdDev = math:sqrt((SumSquare - Sum*Sum/N)/(N - 1)), - {Mean, StdDev, N}; -mean([Value | List], {Sum, SumSquare, N}) -> - mean(List, {Sum + Value, SumSquare + Value*Value, N + 1}). - - - -activities2count2(Acts, StartTs) -> - Start = inactive_start_states(Acts), - activities2count2(Acts, StartTs, Start, []). - -activities2count2([], _, _, Out) -> lists:reverse(Out); -activities2count2([#activity{ id = Id, timestamp = Ts, state = active} | Acts], StartTs, {Proc,Port}, Out) when is_pid(Id) -> - activities2count2(Acts, StartTs, {Proc + 1, Port}, [{?seconds(Ts, StartTs), Proc + 1, Port}|Out]); -activities2count2([#activity{ id = Id, timestamp = Ts, state = inactive} | Acts], StartTs, {Proc,Port}, Out) when is_pid(Id) -> - activities2count2(Acts, StartTs, {Proc - 1, Port}, [{?seconds(Ts, StartTs), Proc - 1, Port}|Out]); -activities2count2([#activity{ id = Id, timestamp = Ts, state = active} | Acts], StartTs, {Proc,Port}, Out) when is_port(Id) -> - activities2count2(Acts, StartTs, {Proc, Port + 1}, [{?seconds(Ts, StartTs), Proc, Port + 1}|Out]); -activities2count2([#activity{ id = Id, timestamp = Ts, state = inactive} | Acts], StartTs, {Proc,Port}, Out) when is_port(Id) -> - activities2count2(Acts, StartTs, {Proc, Port - 1}, [{?seconds(Ts, StartTs), Proc, Port - 1}|Out]). - - -inactive_start_states(Acts) -> - D = activity_start_states(Acts, dict:new()), - dict:fold(fun - (K, inactive, {Procs, Ports}) when is_pid(K) -> {Procs + 1, Ports}; - (K, inactive, {Procs, Ports}) when is_port(K) -> {Procs, Ports + 1}; - (_, _, {Procs, Ports}) -> {Procs, Ports} - end, {0,0}, D). -activity_start_states([], D) -> D; -activity_start_states([#activity{id = Id, state = State}|Acts], D) -> - case dict:is_key(Id, D) of - true -> activity_start_states(Acts, D); - false -> activity_start_states(Acts, dict:store(Id, State, D)) - end. - - - - -%% @spec activities2count(#activity{}, timestamp()) -> Result -%% Result = [{Time, ProcessCount, PortCount}] -%% Time = float() -%% ProcessCount = integer() -%% PortCount = integer() -%% @doc Calculate the resulting active processes and ports during -%% the activity interval. -%% Also checks active/inactive consistency. -%% A task will always begin with an active state and end with an inactive state. - -activities2count(Acts, StartTs) when is_list(Acts) -> activities2count(Acts, StartTs, separated). - -activities2count(Acts, StartTs, Type) when is_list(Acts) -> activities2count_loop(Acts, {StartTs, {0,0}}, Type, []). - -activities2count_loop([], _, _, Out) -> lists:reverse(Out); -activities2count_loop( - [#activity{ timestamp = Ts, id = Id, runnable_count = Rc} | Acts], - {StartTs, {Procs, Ports}}, separated, Out) -> - - Time = ?seconds(Ts, StartTs), - case Id of - Id when is_port(Id) -> - Entry = {Time, Procs, Rc}, - activities2count_loop(Acts, {StartTs, {Procs, Rc}}, separated, [Entry | Out]); - Id when is_pid(Id) -> - Entry = {Time, Rc, Ports}, - activities2count_loop(Acts, {StartTs, {Rc, Ports}}, separated, [Entry | Out]); - _ -> - activities2count_loop(Acts, {StartTs,{Procs, Ports}}, separated, Out) - end; -activities2count_loop( - [#activity{ timestamp = Ts, id = Id, runnable_count = Rc} | Acts], - {StartTs, {Procs, Ports}}, summated, Out) -> - - Time = ?seconds(Ts, StartTs), - case Id of - Id when is_port(Id) -> - Entry = {Time, Procs + Rc}, - activities2count_loop(Acts, {StartTs, {Procs, Rc}}, summated, [Entry | Out]); - Id when is_pid(Id) -> - Entry = {Time, Rc + Ports}, - activities2count_loop(Acts, {StartTs, {Rc, Ports}}, summated, [Entry | Out]) - end. - -%% @spec waiting_activities([#activity{}]) -> FunctionList -%% FunctionList = [{Seconds, Mfa, {Mean, StdDev, N}}] -%% Seconds = float() -%% Mfa = mfa() -%% Mean = float() -%% StdDev = float() -%% N = integer() -%% @doc Calculates the time, both average and total, that a process has spent -%% in a receive state at specific function. However, if there are multiple receives -%% in a function it cannot differentiate between them. - -waiting_activities(Activities) -> - ListedMfas = waiting_activities_mfa_list(Activities, []), - Unsorted = lists:foldl( - fun (Mfa, MfaList) -> - {Total, WaitingTimes} = get({waiting_mfa, Mfa}), - - % cleanup - erlang:erase({waiting_mfa, Mfa}), - - % statistics of receive waiting places - Stats = mean(WaitingTimes), - - [{Total, Mfa, Stats} | MfaList] - end, [], ListedMfas), - lists:sort(fun ({A,_,_},{B,_,_}) -> - if - A > B -> true; - true -> false - end - end, Unsorted). - - -%% Generate lists of receive waiting times per mfa -%% Out: -%% ListedMfas = [mfa()] -%% Intrisnic: -%% get({waiting, mfa()}) -> -%% [{waiting, mfa()}, {Total, [WaitingTime]}) -%% WaitingTime = float() - -waiting_activities_mfa_list([], ListedMfas) -> ListedMfas; -waiting_activities_mfa_list([Activity|Activities], ListedMfas) -> - #activity{id = Pid, state = Act, timestamp = Time, where = MFA} = Activity, - case Act of - active -> - waiting_activities_mfa_list(Activities, ListedMfas); - inactive -> - % Want to know how long the wait is in a receive, - % it is given via the next activity - case Activities of - [] -> - [Info] = percept_db:select(information, Pid), - case Info#information.stop of - undefined -> - % get profile end time - Waited = ?seconds( - percept_db:select({system,stop_ts}), - Time); - Time2 -> - Waited = ?seconds(Time2, Time) - end, - case get({waiting_mfa, MFA}) of - undefined -> - put({waiting_mfa, MFA}, {Waited, [Waited]}), - [MFA | ListedMfas]; - {Total, TimedMfa} -> - put({waiting_mfa, MFA}, {Total + Waited, [Waited | TimedMfa]}), - ListedMfas - end; - [#activity{timestamp=Time2, id = Pid, state = active} | _ ] -> - % Calculate waiting time - Waited = ?seconds(Time2, Time), - % Get previous entry - - case get({waiting_mfa, MFA}) of - undefined -> - % add entry to list - put({waiting_mfa, MFA}, {Waited, [Waited]}), - waiting_activities_mfa_list(Activities, [MFA|ListedMfas]); - {Total, TimedMfa} -> - put({waiting_mfa, MFA}, {Total + Waited, [Waited | TimedMfa]}), - waiting_activities_mfa_list(Activities, ListedMfas) - end; - _ -> error - end - end. - -%% seconds2ts(Seconds, StartTs) -> TS -%% In: -%% Seconds = float() -%% StartTs = timestamp() -%% Out: -%% TS = timestamp() - -%% @spec seconds2ts(float(), StartTs::{integer(),integer(),integer()}) -> timestamp() -%% @doc Calculates a timestamp given a duration in seconds and a starting timestamp. - -seconds2ts(Seconds, {Ms, S, Us}) -> - % Calculate mega seconds integer - MsInteger = trunc(Seconds) div 1000000 , - - % Calculate the reminder for seconds - SInteger = trunc(Seconds), - - % Calculate the reminder for micro seconds - UsInteger = trunc((Seconds - SInteger) * 1000000), - - % Wrap overflows - - UsOut = (UsInteger + Us) rem 1000000, - SOut = ((SInteger + S) + (UsInteger + Us) div 1000000) rem 1000000, - MsOut = (MsInteger+ Ms) + ((SInteger + S) + (UsInteger + Us) div 1000000) div 1000000, - - {MsOut, SOut, UsOut}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% Analyze interval for concurrency -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% @spec analyze_activities(integer(), [#activity{}]) -> [{integer(),#activity{}}] -%% @hidden - -analyze_activities(Threshold, Activities) -> - RunnableCount = runnable_count(Activities, 0), - analyze_runnable_activities(Threshold, RunnableCount). - - -%% runnable_count(Activities, StartValue) -> RunnableCount -%% In: -%% Activities = [activity()] -%% StartValue = integer() -%% Out: -%% RunnableCount = [{integer(), activity()}] -%% Purpose: -%% Calculate the runnable count of a given interval of generic -%% activities. - -%% @spec runnable_count([#activity{}]) -> [{integer(),#activity{}}] -%% @hidden - -runnable_count(Activities) -> - Threshold = runnable_count_threshold(Activities), - runnable_count(Activities, Threshold, []). - -runnable_count_threshold(Activities) -> - CountedActs = runnable_count(Activities, 0), - Counts = [C || {C, _} <- CountedActs], - Min = lists:min(Counts), - 0 - Min. -%% @spec runnable_count([#activity{}],integer()) -> [{integer(),#activity{}}] -%% @hidden - -runnable_count(Activities, StartCount) when is_integer(StartCount) -> - runnable_count(Activities, StartCount, []). -runnable_count([], _ , Out) -> - lists:reverse(Out); -runnable_count([A | As], PrevCount, Out) -> - case A#activity.state of - active -> - runnable_count(As, PrevCount + 1, [{PrevCount + 1, A} | Out]); - inactive -> - runnable_count(As, PrevCount - 1, [{PrevCount - 1, A} | Out]) - end. - -%% In: -%% Threshold = integer(), -%% RunnableActivities = [{Rc, activity()}] -%% Rc = integer() - -analyze_runnable_activities(Threshold, RunnableActivities) -> - analyze_runnable_activities(Threshold, RunnableActivities, []). - -analyze_runnable_activities( _z, [], Out) -> - lists:reverse(Out); -analyze_runnable_activities(Threshold, [{Rc, Act} | RunnableActs], Out) -> - if - Rc =< Threshold -> - analyze_runnable_activities(Threshold, RunnableActs, [{Rc,Act} | Out]); - true -> - analyze_runnable_activities(Threshold, RunnableActs, Out) - end. - -%% minmax_activity(Activities, Count) -> {Min, Max} -%% In: -%% Activities = [activity()] -%% InitialCount = non_neg_integer() -%% Out: -%% {Min, Max} -%% Min = non_neg_integer() -%% Max = non_neg_integer() -%% Purpose: -%% Minimal and maximal activity during an activity interval. -%% Initial activity count needs to be supplied. - -%% @spec minmax_activities([#activity{}], integer()) -> {integer(), integer()} -%% @doc Calculates the minimum and maximum of runnable activites (processes -% and ports) during the interval of reffered by the activity list. - -minmax_activities(Activities, Count) -> - minmax_activities(Activities, Count, {Count, Count}). -minmax_activities([], _, Out) -> - Out; -minmax_activities([A|Acts], Count, {Min, Max}) -> - case A#activity.state of - active -> - minmax_activities(Acts, Count + 1, {Min, lists:max([Count + 1, Max])}); - inactive -> - minmax_activities(Acts, Count - 1, {lists:min([Count - 1, Min]), Max}) - end. |