From: Siraaj Khandkar Date: Wed, 16 Sep 2015 23:18:30 +0000 (-0400) Subject: Sketch process origin identification. X-Git-Tag: 0.7.0^2~3 X-Git-Url: https://git.xandkar.net/?p=beam_stats.git;a=commitdiff_plain;h=f2adf421655bc81b4563f2635be271a9f956daf8 Sketch process origin identification. --- diff --git a/src/beam_stats_process.erl b/src/beam_stats_process.erl index 412b4f8..9b2ae8a 100644 --- a/src/beam_stats_process.erl +++ b/src/beam_stats_process.erl @@ -5,10 +5,13 @@ -export_type( [ t/0 , status/0 + , ancestor/0 + , best_known_origin/0 ]). -export( [ of_pid/1 + , best_known_origin/1 , print/1 ]). @@ -21,6 +24,17 @@ | waiting . +-type ancestor() :: + {otp_ancestors , [pid() | atom()]} + | {otp_initial_call , mfa()} + | {raw_initial_call , mfa()} + . + +-type best_known_origin() :: + {registered_name , atom()} + | {ancestry , [ancestor()]} + . + -define(T, #?MODULE). -type t() :: @@ -61,11 +75,13 @@ print( , total_heap_size = TotalHeapSize , stack_size = StackSize , message_queue_len = MsgQueueLen - } + }=T ) -> + BestKnownOrigin = best_known_origin(T), io:format("--------------------------------------------------~n"), io:format( "Pid : ~p~n" + "BestKnownOrigin : ~p~n" "RegisteredNameOpt : ~p~n" "InitialCallRaw : ~p~n" "InitialCallOTPOpt : ~p~n" @@ -77,6 +93,7 @@ print( "MsgQueueLen : ~p~n" "~n", [ Pid + , BestKnownOrigin , RegisteredNameOpt , InitialCallRaw , InitialCallOTPOpt @@ -102,3 +119,52 @@ pid_info_opt(Pid, Key) -> of {registered_name, []} -> none ; {_ , {Key, Value}} -> {some, Value} end. + +%% ============================================================================ +%% Process code origin approximation or naming the anonymous processes. +%% +%% At runtime, given a PID, how precicely can we identify the origin of the +%% code it is running? +%% +%% We have these data points: +%% +%% - Sometimes | registered name (if so, we're done) +%% - Sometimes | ancestor PIDs or registered names +%% - Always | initial_call (can be too generic, such as erlang:apply) +%% - Always | current_function (can be too far down the stack) +%% - Always | current_location (can be too far down the stack) +%% - Potentially | application tree, but maybe expensive to compute, need to check +%% ============================================================================ + +-define(TAG(Tag), fun (X) -> {Tag, X} end). + +-spec best_known_origin(t()) -> + best_known_origin(). +best_known_origin(?T{registered_name={some, RegisteredName}}) -> + {registered_name, RegisteredName}; +best_known_origin( + ?T + { pid = _Pid + , registered_name = none + , raw_initial_call = InitCallRaw + , otp_initial_call = InitCallOTPOpt1 + , otp_ancestors = AncestorsOpt1 + , status = _Status + , memory = _Memory + , total_heap_size = _TotalHeapSize + , stack_size = _StackSize + , message_queue_len = _MsgQueueLen + } +) -> + ToSingleton = fun (X) -> [X] end, + InitCallOTPOpt2 = hope_option:map(InitCallOTPOpt1, ?TAG(otp_initial_call)), + AncestorsOpt2 = hope_option:map(AncestorsOpt1 , ?TAG(otp_ancestors)), + InitCallOTPOpt3 = hope_option:map(InitCallOTPOpt2, ToSingleton), + AncestorsOpt3 = hope_option:map(AncestorsOpt2 , ToSingleton), + MaybeInitCallOTP = hope_option:get(InitCallOTPOpt3, []), + MaybeAncestors = hope_option:get(AncestorsOpt3 , []), + Ancestry = + [{raw_initial_call, InitCallRaw}] ++ + MaybeInitCallOTP ++ + MaybeAncestors, + {ancestry, Ancestry}.