diff --git a/ChangeLog b/ChangeLog index 4ead2b917..723c20281 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-05-08 Mickael Remond + + * src/ejabberd_app.erl: Better support for profiling. + * src/ejabberd.erl: Likewise + * src/ejabberd_ctl.erl: Likewise + * src/ejabberd_debug.erl: Likewise + 2009-05-07 Christophe Romain * src/mod_caps.erl: Set debug message to DEBUG (from debian patch, diff --git a/src/ejabberd.erl b/src/ejabberd.erl index bc23dd80e..0c7c56a2a 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -31,11 +31,12 @@ get_so_path/0, get_bin_path/0]). start() -> + %%ejabberd_cover:start(), application:start(ejabberd). stop() -> application:stop(ejabberd). - + %%ejabberd_cover:stop(). get_so_path() -> case os:getenv("EJABBERD_SO_PATH") of diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 9a4cbe2c7..452346023 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -60,9 +60,8 @@ start(normal, _Args) -> ejabberd_auth:start(), cyrsasl:start(), % Profiling - %eprof:start(), - %eprof:profile([self()]), - %fprof:trace(start, "/tmp/fprof"), + %ejabberd_debug:eprof_start(), + %fprof:trace([start, {file, "/tmp/fprof"}, {procs, ejabberd_debug:pids()}]), maybe_add_nameservers(), start_modules(), ejabberd_listener:start_listeners(), @@ -82,6 +81,7 @@ prep_stop(State) -> %% All the processes were killed when this function is called stop(_State) -> ?INFO_MSG("ejabberd ~s is stopped in the node ~p", [?VERSION, node()]), + ejabberd_debug:stop(), ok. diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 32b1ea9d2..264bbaa53 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -143,6 +143,7 @@ process(["status"]) -> end; process(["stop"]) -> + %%ejabberd_cover:stop(), init:stop(), ?STATUS_SUCCESS; diff --git a/src/ejabberd_debug.erl b/src/ejabberd_debug.erl new file mode 100644 index 000000000..62641d6f5 --- /dev/null +++ b/src/ejabberd_debug.erl @@ -0,0 +1,93 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_debug.erl +%%% Author : Mickael Remond +%%% Purpose : ejabberd's application callback module +%%% Created : 6 may 2009 by Mickael Remond +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2009 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software +%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +%%% 02111-1307 USA +%%% +%%%---------------------------------------------------------------------- + +-module(ejabberd_debug). + +-export([eprof_start/0, stop/0]). +-export([pids/0]). + +eprof_start() -> + eprof:start(), + eprof:profile(pids()). + +%% Stop all profilers +stop() -> + catch eprof:stop(), + ok. + +pids() -> + lists:zf( + fun(Pid) -> + case process_info(Pid) of + ProcessInfo when list(ProcessInfo) -> + CurrentFunction = current_function(ProcessInfo), + InitialCall = initial_call(ProcessInfo), + RegisteredName = registered_name(ProcessInfo), + Ancestor = ancestor(ProcessInfo), + filter_pid(Pid, CurrentFunction, InitialCall, RegisteredName, Ancestor); + _ -> + false + end + end, + processes()). + +current_function(ProcessInfo) -> + {value, {_, {CurrentFunction, _,_}}} = + lists:keysearch(current_function, 1, ProcessInfo), + atom_to_list(CurrentFunction). + +initial_call(ProcessInfo) -> + {value, {_, {InitialCall, _,_}}} = + lists:keysearch(initial_call, 1, ProcessInfo), + atom_to_list(InitialCall). + +registered_name(ProcessInfo) -> + case lists:keysearch(registered_name, 1, ProcessInfo) of + {value, {_, Name}} when is_atom(Name) -> atom_to_list(Name); + _ -> "" + end. + +ancestor(ProcessInfo) -> + {value, {_, Dictionary}} = lists:keysearch(dictionary, 1, ProcessInfo), + case lists:keysearch('$ancestors', 1, Dictionary) of + {value, {_, [Ancestor|_T]}} when is_atom(Ancestor) -> + atom_to_list(Ancestor); + _ -> + "" + end. + +filter_pid(Pid, "ejabberd" ++ _, _InitialCall, _RegisteredName, _Ancestor) -> + {true, Pid}; +filter_pid(Pid, _CurrentFunction, "ejabberd" ++ _, _RegisteredName, _Ancestor) -> + {true, Pid}; +filter_pid(Pid, _CurrentFunction, _InitialCall, "ejabberd"++_, _Ancestor) -> + {true, Pid}; +filter_pid(Pid, _CurrentFunction, _InitialCall, "stringprep"++_, _Ancestor) -> + {true, Pid}; +filter_pid(Pid, _CurrentFunction, _InitialCall, _RegisteredName, "ejabberd"++_) -> + {true, Pid}; +filter_pid(_Pid, _CurrentFunction, _InitialCall, _RegisteredName, _Ancestor) -> + false.