aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/test/megaco_profile.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/test/megaco_profile.erl')
-rw-r--r--lib/megaco/test/megaco_profile.erl138
1 files changed, 138 insertions, 0 deletions
diff --git a/lib/megaco/test/megaco_profile.erl b/lib/megaco/test/megaco_profile.erl
new file mode 100644
index 0000000000..01fa0b5a14
--- /dev/null
+++ b/lib/megaco/test/megaco_profile.erl
@@ -0,0 +1,138 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. 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 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% megaco_profile: Utility module used for megaco profiling
+%%----------------------------------------------------------------------
+
+-module(megaco_profile).
+
+-export([profile/2]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Execute Fun and profile it with fprof.
+profile(Slogan, Fun) when is_function(Fun) ->
+ Pids = [self()],
+ profile(Slogan, Fun, Pids).
+
+profile(Slogan, Fun, Pids) ->
+ TraceFile = lists:concat(["profile_", Slogan, "-fprof.trace"]),
+ DestFile = lists:concat(["profile_", Slogan, ".fprof"]),
+ TreeFile = lists:concat(["profile_", Slogan, ".calltree"]),
+ erlang:garbage_collect(),
+ {ok, _Pid} = fprof:start(),
+ TraceOpts = [start,
+ {cpu_time, false},
+ {procs, Pids},
+ {file, TraceFile}
+ ],
+ ok = fprof:trace(TraceOpts),
+ Res = (catch Fun()),
+ ok = fprof:trace(stop),
+ ok = fprof:profile([{file, TraceFile}]),
+ ok = fprof:analyse([{dest, DestFile}]),
+ ok = fprof:stop(),
+ ok = file:delete(TraceFile),
+ reformat_total(DestFile, TreeFile),
+ Res.
+
+reformat_total(FromFile, ToFile) ->
+ {ok, ConsultedFromFile} = file:consult(FromFile),
+ [_AnalysisOpts, [Totals] | Terms] = ConsultedFromFile,
+ {totals, _, TotalAcc, _} = Totals,
+ {ok, Fd} = file:open(ToFile, [write, raw]),
+ Indent = "",
+ log(Fd, Indent, TotalAcc, Totals),
+ Processes = split_processes(Terms, [], []),
+ Reformat = fun(P) -> reformat_process(Fd, " " ++ Indent, TotalAcc, P) end,
+ lists:foreach(Reformat, Processes),
+ file:close(Fd).
+
+
+split_processes([H | T], ProcAcc, TotalAcc) ->
+ if
+ is_tuple(H) ->
+ split_processes(T, [H | ProcAcc], TotalAcc);
+ is_list(H), ProcAcc =:= [] ->
+ split_processes(T, [H], TotalAcc);
+ is_list(H) ->
+ split_processes(T, [H], [lists:reverse(ProcAcc) | TotalAcc])
+ end;
+split_processes([], [], TotalAcc) ->
+ lists:reverse(TotalAcc);
+split_processes([], ProcAcc, TotalAcc) ->
+ lists:reverse([lists:reverse(ProcAcc) | TotalAcc]).
+
+reformat_process(Fd, Indent, TotalAcc, Terms) ->
+ case Terms of
+ [[{ProcLabel, _, _, _}] | All] -> ok;
+ [[{ProcLabel,_,_,_} | _] | All] -> ok
+ end,
+ [{_, {TopKey, TopCnt, TopAcc, TopOwn}, _} | _] = All,
+ Process = {ProcLabel, TopCnt, TopAcc, TopOwn},
+ log(Fd, Indent, TotalAcc, Process),
+ reformat_calls(Fd, " " ++ Indent, TotalAcc, TopKey, All, []).
+
+reformat_calls(Fd, Indent, TotalAcc, Key, Terms, Stack) ->
+ {_CalledBy, Current, Calls} = find(Key, Terms),
+ log(Fd, Indent, TotalAcc, Current),
+ case lists:member(Key, Stack) of
+ true ->
+ ok;
+ false ->
+ case Key of
+ {io_lib, _, _} ->
+ ok;
+ {disk_log, _, _} ->
+ ok;
+ {lists, flatten, _} ->
+ ok;
+ {lists, keysort, _} ->
+ ok;
+ _ ->
+ Fun = fun({NextKey, _, _, _}) ->
+ reformat_calls(Fd,
+ " " ++ Indent,
+ TotalAcc,
+ NextKey,
+ Terms,
+ [Key | Stack])
+ end,
+ lists:foreach(Fun, Calls)
+ end
+ end.
+
+find(Key, [{_, {Key, _, _, _}, _} = H | _]) ->
+ H;
+find(Key, [{_, {_, _, _, _}, _} | T]) ->
+ find(Key, T).
+
+log(Fd, Indent, Total, {Label, Cnt, Acc, Own}) ->
+ Percent = case Acc of
+ undefined -> 100;
+ _ -> trunc((lists:max([Acc, Own]) * 100) / Total)
+ end,
+ Label2 = io_lib:format("~p", [Label]),
+ IoList = io_lib:format("~s~p% ~s \t~p \t~p \t~p\n",
+ [Indent, Percent, Label2, Cnt, trunc(Acc), trunc(Own)]),
+ file:write(Fd, IoList).
+