aboutsummaryrefslogtreecommitdiffstats
path: root/lib/percept/src/percept_analyzer.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/percept/src/percept_analyzer.erl')
-rw-r--r--lib/percept/src/percept_analyzer.erl368
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.