1%% -*- erlang-indent-level: 2 -*- 2%% 3%% Licensed under the Apache License, Version 2.0 (the "License"); 4%% you may not use this file except in compliance with the License. 5%% You may obtain a copy of the License at 6%% 7%% http://www.apache.org/licenses/LICENSE-2.0 8%% 9%% Unless required by applicable law or agreed to in writing, software 10%% distributed under the License is distributed on an "AS IS" BASIS, 11%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12%% See the License for the specific language governing permissions and 13%% limitations under the License. 14%% 15%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16%% Copyright (c) 2001 by Erik Johansson. All Rights Reserved 17%% ==================================================================== 18%% Module : hipe_profile 19%% Purpose : 20%% History : * 2001-07-12 Erik Johansson (happi@it.uu.se): Created. 21%% ==================================================================== 22%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 24-module(hipe_profile). 25 26-export([%% profile/1, mods_profile/1, 27 prof/0, prof_off/0, clear/0, res/0, 28 mods_res/0, 29 %% clear_module/1, res_module/1, 30 prof_module/1, prof_module_off/1]). 31 32%% %% @spec mods_profile(F) -> [{mod(),calls()}] 33%% %% F = () -> term() 34%% %% mod() = atom() 35%% %% calls()= integer() 36%% %% 37%% %% @doc Returns the number of calls per module generated by 38%% %% applying F(). 39%% %% The resulting lists is sorted with the most called 40%% %% module first. 41%% mods_profile(F) -> 42%% F(), 43%% prof(), 44%% clear(), 45%% F(), 46%% R = mods_res(), 47%% prof_off(), 48%% R. 49 50-spec mods_res() -> [{atom(), non_neg_integer()}]. 51%% @doc Returns the number of calls per module currently 52%% recordeed since hipe_bifs:call_count_on(). 53%% The resulting list is sorted with the most called 54%% module first. 55mods_res() -> 56 lists:reverse(lists:keysort(2, calls())). 57 58-spec calls() -> [{atom(), non_neg_integer()}]. 59%% @doc Returns the number of calls per module currently 60%% recordeed since hipe_bifs:call_count_on(). 61calls() -> 62 [{Mod, total_calls(Mod)} || Mod <- mods(), 63 total_calls(Mod) > 1, 64 Mod =/= hipe_profile]. 65 66%% %% @spec profile(F) -> [{mfa(),calls()}] 67%% %% F = () -> term() 68%% %% mfa() = {mod(),function(),arity()} 69%% %% function() = atom() 70%% %% arity() = intger() 71%% %% 72%% %% @doc Returns the number of calls per module generated by 73%% %% applying F(). 74%% %% The resulting lists is sorted with the most called 75%% %% module first. 76%% profile(F) -> 77%% %% Make sure all code is loaded. 78%% F(), 79%% %% Turn profiling on. 80%% prof(), 81%% clear(), 82%% %% Apply the closure to profile. 83%% F(), 84%% %% Get result. 85%% R = res(), 86%% %% Turn off profiling. 87%% prof_off(), 88%% R. 89 90-spec prof() -> 'ok'. 91%% @doc Turns on profiling of all loaded modules. 92prof() -> 93 lists:foreach(fun prof_module/1, mods()). 94 95-spec prof_off() -> 'ok'. 96%% @doc Turns off profiling of all loaded modules. 97 prof_off() -> 98 lists:foreach(fun prof_module_off/1, mods()). 99 100-spec clear() -> 'ok'. 101%% @doc Clears all counters. 102clear() -> 103 lists:foreach(fun clear_module/1, mods()). 104 105-spec res() -> [{mfa(), non_neg_integer()}]. 106%% @doc Returns a list of the numbers of calls to each profiled function. 107%% The list is sorted with the most called function first. 108res() -> 109 lists:reverse(lists:keysort(2, lists:flatten([res_module(M) || M <- mods()]))). 110 111%% -------------------------------------------------------------------- 112-spec mods() -> [atom()]. 113%% @doc Returns a list of all loaded modules. 114%@ -------------------------------------------------------------------- 115 116mods() -> 117 [Mod || {Mod,_} <- code:all_loaded()]. 118 119%% -------------------------------------------------------------------- 120-spec prof_module(atom()) -> 'ok'. 121%% @doc Turns on profiling for given module. 122%@ ____________________________________________________________________ 123 124prof_module(Mod) -> 125 Funs = Mod:module_info(functions), 126 lists:foreach(fun ({F,A}) -> catch hipe_bifs:call_count_on({Mod,F,A}) end, 127 Funs), 128 ok. 129 130%% -------------------------------------------------------------------- 131-spec prof_module_off(atom()) -> 'ok'. 132%% @doc Turns off profiling of the module Mod. 133%@ -------------------------------------------------------------------- 134 135prof_module_off(Mod) -> 136 Funs = Mod:module_info(functions), 137 lists:foreach(fun ({F,A}) -> catch hipe_bifs:call_count_off({Mod,F,A}) end, 138 Funs), 139 ok. 140 141%% -------------------------------------------------------------------- 142-spec clear_module(atom()) -> 'ok'. 143%% @doc Clears the call counters for all functions in module Mod. 144%@ -------------------------------------------------------------------- 145 146clear_module(Mod) -> 147 Funs = Mod:module_info(functions), 148 lists:foreach(fun ({F,A}) -> catch hipe_bifs:call_count_clear({Mod,F,A}) end, 149 Funs), 150 ok. 151 152%% -------------------------------------------------------------------- 153-spec res_module(atom()) -> [{mfa(), non_neg_integer()}]. 154%% @doc Returns the number of profiled calls to each function (MFA) 155%% in the module Mod. 156%@ -------------------------------------------------------------------- 157 158res_module(Mod) -> 159 Fun = fun ({F,A}) when is_atom(F), is_integer(A) -> 160 MFA = {Mod,F,A}, 161 {MFA, try hipe_bifs:call_count_get(MFA) of 162 N when is_integer(N) -> N; 163 false -> 0 164 catch 165 _:_ -> 0 166 end 167 } 168 end, 169 lists:reverse(lists:keysort(2, [Fun(FA) || FA <- Mod:module_info(functions)])). 170 171-spec total_calls(atom()) -> non_neg_integer(). 172 173total_calls(Mod) -> 174 Funs = Mod:module_info(functions), 175 SumF = fun ({F,A}, Acc) -> 176 MFA = {Mod,F,A}, 177 try hipe_bifs:call_count_get(MFA) of 178 N when is_integer(N) -> N+Acc; 179 false -> Acc 180 catch 181 _:_ -> Acc 182 end; 183 (_, Acc) -> Acc 184 end, 185 lists:foldl(SumF, 0, Funs). 186