⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fprof.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 5 页
字号:
				    end,			  sort = case Sort of				     [] -> 					 acc;				     [{sort, acc}] ->					 acc;				     [{sort, own}] ->					 own;				     _ ->					 erlang:fault(badarg, [Options])				 end,			  totals = case Totals of				       [] -> 					   false;				       [totals] ->					   true;				       [{totals, true}] ->					   true;				       [{totals, false}] ->					   false;				       _ ->					   erlang:fault(badarg, [Options])				   end,			  details = case {Details, NoDetails} of					{[], []} ->					    true;					{[details], []} ->					    true;					{[{details, true}], []} ->					    true;					{[{details, false}], []} ->					    false;					{[], [no_details]} ->					    false;				       _ ->					   erlang:fault(badarg, [Options])				    end});  	_ ->	    erlang:fault(badarg, [Options])    end;analyse(Options) ->    erlang:fault(badarg, [Options]).%%----------------%% Debug functions%%----------------get_state() ->    just_call(#get_state{}).save_profile() ->    save_profile([]).save_profile(Option, Value) when is_atom(Option) ->    save_profile([{Option, Value}]);save_profile(Option, Value) ->    erlang:fault(badarg, [Option, Value]).save_profile(Option) when is_atom(Option) ->    save_profile([Option]);save_profile(Options) when is_list(Options) ->    case getopts(Options, [file]) of	{[File], []} ->	    call(#save_profile{file = case File of					  [] -> 					      ?PROFILE_FILE;					  [{file, F}] ->					      F;					  _ ->					      erlang:fault(badarg, [Options])				      end});  	_ ->	    erlang:fault(badarg, [Options])    end;save_profile(Options) ->    erlang:fault(badarg, [Options]).load_profile() ->    load_profile([]).load_profile(Option, Value) when is_atom(Option) ->    load_profile([{Option, Value}]);load_profile(Option, Value) ->    erlang:fault(badarg, [Option, Value]).load_profile(Option) when is_atom(Option) ->    load_profile([Option]);load_profile(Options) when is_list(Options) ->    case getopts(Options, [file]) of	{[File], []} ->	    call(#load_profile{file = case File of					  [] -> 					      ?PROFILE_FILE;					  [{file, F}] ->					      F;					  _ ->					      erlang:fault(badarg, [Options])				      end});  	_ ->	    erlang:fault(badarg, [Options])    end;load_profile(Options) ->    erlang:fault(badarg, [Options]).code_change() ->    just_call('$code_change').%%%----------------------------------------------------------------------%%% ETS table record definitions%%% The field 'id' must be first in these records;%%% it is the common ets table index field.%%%-----------------------------------------------------------------------record(clocks, {	  id,	  cnt = 0,   % Number of calls	  own = 0,   % Own time (wall clock)	  acc = 0}). % Accumulated time : own + subfunctions (wall clock)-record(proc, {	  id,	  parent,	  spawned_as,     % Spawned MFArgs	  init_log = [],  % List of first calls, head is newest	  init_cnt = 2}). % First calls counter, counts down to 0-record(misc, {id, 	       data}).%% Analysis summary record-record(funcstat, {	  callers_sum,   % #clocks{id = {Pid, Caller, Func}}	  called_sum,    % #clocks{id = {Pid, Caller, Func}}	  callers = [],  % [#clocks{}, ...]	  called = []}). % [#clocks{}, ...]%%%----------------------------------------------------------------------%%% ?FPROF_SERVER%%%----------------------------------------------------------------------%%%-------------------%%% Exported functions%%%-------------------%% Start server processstart() ->    spawn_3step(      fun () ->	      try register(?FPROF_SERVER, self()) of		  true ->		      process_flag(trap_exit, true),		      {{ok, self()}, loop}	      catch		  error:badarg ->		      {{error, {already_started, whereis(?FPROF_SERVER)}},		       already_started}	      end      end,      fun (X) ->	      X      end,      fun (loop) ->	      put(trace_state, idle),	      put(profile_state, {idle, undefined}),	      put(pending_stop, []),	      server_loop([]);	  (already_started) ->	      ok      end).%% Stop server processstop() ->    stop(normal).stop(kill) ->    case whereis(?FPROF_SERVER) of	undefined ->	    ok;	Pid ->	    exit(Pid, kill),	    ok    end;stop(Reason) ->    just_call(#stop{reason = Reason}),    ok.%%%------------------------%%% Client helper functions%%%------------------------%% Send request to server process and return the server's reply.%% First start server if it ain't started.call(Request) ->    case whereis(?FPROF_SERVER) of	undefined ->	    start(),	    just_call(Request);	Server ->	    just_call(Server, Request)    end.%% Send request to server process, and return the server's reply.%% Returns {'EXIT', Pid, Reason} if the server dies during the%% call, or if it wasn't started.just_call(Request) ->    just_call(whereis(?FPROF_SERVER), Request).just_call(undefined, _) ->    {'EXIT', ?FPROF_SERVER, noproc};just_call(Pid, Request) ->    Mref = erlang:monitor(process, Pid),    receive	{'DOWN', Mref, _, _, Reason} ->	    {'EXIT', Pid, Reason}    after 0 ->	    Tag = {Mref, self()},	    {T, Demonitor} = case Request of				 #stop{} ->				     {?FPROF_SERVER_TIMEOUT, false};				 _ ->				     {0, true}			     end,	    %% io:format("~p request: ~p~n", [?MODULE, Request]),	    catch Pid ! {?FPROF_SERVER, Tag, Request},	    receive		{?FPROF_SERVER, Mref, Reply} ->		    case Demonitor of			true -> erlang:demonitor(Mref);			false -> ok		    end,		    receive {'DOWN', Mref, _, _, _} -> ok after T -> ok end,		    Reply;		{'DOWN', Mref, _, _, Reason} ->		    receive {?FPROF_SERVER, Mref, _} -> ok after T -> ok end,		    {'EXIT', Pid, Reason}	    after ?FPROF_SERVER_TIMEOUT ->		    timeout	    end    end.%%%------------------------%%% Server helper functions%%%------------------------%% Return the reply to the client's request.reply({Mref, Pid}, Reply) when is_reference(Mref), is_pid(Pid) ->    catch Pid ! {?FPROF_SERVER, Mref, Reply},    ok.server_loop(State) ->        receive 	{?FPROF_SERVER, {Mref, Pid} = Tag, '$code_change'} 	when is_reference(Mref), is_pid(Pid) ->	    reply(Tag, ok),	    ?MODULE:'$code_change'(State);	{?FPROF_SERVER, {Mref, Pid} = Tag, Request} 	when is_reference(Mref), is_pid(Pid) ->	    server_loop(handle_req(Request, Tag, State));	Other ->	    server_loop(handle_other(Other, State))    end.%-export.'$code_change'(State) ->    case lists:keysearch(time, 1, module_info(compile)) of	{value, {time, {Y, M, D, HH, MM, SS}}} ->	    io:format("~n~w: code change to compile time "		      ++"~4..0w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w~n",		      [?MODULE, Y, M, D, HH, MM, SS]);	false ->	    ok    end,    server_loop(State).%% Server help function that stops the server iff the%% sub state machines are in proper states. Sends the reply%% to all waiting clients.try_pending_stop(State) ->    case {get(trace_state), get(profile_state), get(pending_stop)} of	{idle, {idle, _}, [_|_] = PendingStop} ->	    Reason = get(stop_reason),	    Reply = result(Reason),	    lists:foreach(	      fun (Tag) ->		      reply(Tag, Reply)	      end,	      PendingStop),	    exit(Reason);	_ ->	    State    end.%%------------------%% Server handle_req			    %%------------------handle_req(#trace_start{procs = Procs,			mode = Mode,			type = file,			dest = Filename}, Tag, State) ->    case {get(trace_state), get(pending_stop)} of	{idle, []} ->	    trace_off(),	    Port = open_dbg_trace_port(file, Filename),	    case trace_on(Procs, Port, Mode) of		ok ->		    put(trace_state, running),		    put(trace_type, file),		    put(trace_pid, Port),		    reply(Tag, ok),		    State;		Error ->		    reply(Tag, Error),		    State	    end;	_ ->	    reply(Tag, {error, already_tracing}),	    State    end;handle_req(#trace_start{procs = Procs,			mode = Mode,			type = tracer,			dest = Tracer}, Tag, State) ->    case {get(trace_state), get(pending_stop)} of	{idle, []} ->	    trace_off(),	    case trace_on(Procs, Tracer, Mode) of		ok ->		    put(trace_state, running),		    put(trace_type, tracer),		    put(trace_pid, Tracer),		    reply(Tag, ok),		    State;		Error ->		    reply(Tag, Error),		    State	    end;	_ ->	    reply(Tag, {error, already_tracing}),	    State    end;handle_req(#trace_stop{}, Tag, State) ->    case get(trace_state) of	running ->	    TracePid = get(trace_pid),	    trace_off(),	    case erase(trace_type) of		file ->		    catch erlang:port_close(TracePid),		    put(trace_state, stopping),		    put(trace_tag, Tag),		    State;		tracer ->		    erase(trace_pid),		    put(trace_state, idle),		    case {get(profile_state), get(profile_type), 			  get(profile_pid)} of			{running, tracer, TracePid} ->			    exit(TracePid, normal),			    put(profile_tag, Tag),			    State;			_ ->			    reply(Tag, ok),			    try_pending_stop(State)		    end	    end;	_ ->	    reply(Tag, {error, not_tracing}),	    State    end;handle_req(#profile{src = Filename,		    group_leader = GroupLeader,		    dump = Dump,		    flags = Flags}, Tag, State) ->    case {get(profile_state), get(pending_stop)} of	{{idle, _}, []} ->	    case ensure_open(Dump, [write | Flags]) of		{already_open, DumpPid} ->		    put(profile_dump, DumpPid),		    put(profile_close_dump, false);		{ok, DumpPid} ->		    put(profile_dump, DumpPid),		    put(profile_close_dump, true);		{error, _} = Error ->		    reply(Tag, Error),		    State	    end,	    Table = ets:new(?MODULE, [set, public, {keypos, #clocks.id}]),	    Pid = spawn_link_dbg_trace_client(Filename, Table, 					      GroupLeader, 					      get(profile_dump)),	    put(profile_state, running),	    put(profile_type, file),	    put(profile_pid, Pid),	    put(profile_tag, Tag),	    put(profile_table, Table),	    State;	_ ->	    reply(Tag, {error, already_profiling}),	    State    end;	    handle_req(#profile_start{group_leader = GroupLeader,			  dump = Dump,			  flags = Flags}, Tag, State) ->    case {get(profile_state), get(pending_stop)} of	{{idle, _}, []} ->	    case ensure_open(Dump, [write | Flags]) of		{already_open, DumpPid} ->		    put(profile_dump, DumpPid),		    put(profile_close_dump, false);		{ok, DumpPid} ->		    put(profile_dump, DumpPid),		    put(profile_close_dump, true);		{error, _} = Error ->		    reply(Tag, Error),		    State	    end,	    Table = ets:new(?MODULE, [set, public, {keypos, #clocks.id}]),	    Pid = spawn_link_trace_client(Table, GroupLeader, 					  get(profile_dump)),	    put(profile_state, running),	    put(profile_type, tracer),	    put(profile_pid, Pid),	    put(profile_table, Table),	    reply(Tag, {ok, Pid}),	    State;	_ ->	    reply(Tag, {error, already_profiling}),	    State    end;handle_req(#profile_stop{}, Tag, State) ->    case {get(profile_state), get(profile_type)} of	{running, tracer} ->	    ProfilePid = get(profile_pid),	    case {get(trace_state), get(trace_type), get(trace_pid)} of		{running, tracer, ProfilePid} ->		    trace_off(),		    erase(trace_type),		    erase(trace_pid),		    put(trace_state, idle);		_ ->		    ok	    end,	    exit(ProfilePid, normal),	    put(profile_tag, Tag),	    State;	{running, file} ->	    reply(Tag, {error, profiling_file}),	    State;	{_, _} ->	    reply(Tag, {error, not_profiling}),	    State    end;handle_req(#analyse{dest = Dest,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -