Last active
July 11, 2017 19:11
-
-
Save essen/2a5739fe1027073c80cb0dc0435e872d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/c_src/lg_tracer.c b/c_src/lg_tracer.c | |
index 8551dbc..6110d7a 100644 | |
--- a/c_src/lg_tracer.c | |
+++ b/c_src/lg_tracer.c | |
@@ -111,6 +111,9 @@ NIF_FUNCTION(enabled) | |
ERL_NIF_TERM tracers, value; | |
ErlNifPid tracer; | |
+ // @todo We can go one step further by having the one pid | |
+ // in its own value in the map, skipping a get_map_value step. | |
+ | |
// This function will only be called for trace_status. | |
// We can take a few shortcuts knowing this. | |
@@ -138,6 +141,11 @@ NIF_FUNCTION(enabled) | |
NIF_FUNCTION(enabled_call) | |
{ | |
+ // @todo Discard trace events for a percent of processes. | |
+ | |
+// if ((enif_hash(ERL_NIF_INTERNAL_HASH, argv[2], 0) % 100) > 10) | |
+// return atom_discard; | |
+ | |
// We always want both call and return_to. | |
return atom_trace; | |
} | |
@@ -153,17 +161,32 @@ NIF_FUNCTION(enabled_procs) | |
return atom_discard; | |
} | |
+ // @todo Discard trace events for a percent of processes. | |
+ | |
+// if ((enif_hash(ERL_NIF_INTERNAL_HASH, argv[2], 0) % 100) > 10) | |
+// return atom_discard; | |
+ | |
return atom_trace; | |
} | |
NIF_FUNCTION(enabled_running_procs) | |
{ | |
+ // @todo Discard trace events for a percent of processes. | |
+ | |
+// if ((enif_hash(ERL_NIF_INTERNAL_HASH, argv[2], 0) % 100) > 10) | |
+// return atom_discard; | |
+ | |
// We always want both in and out. | |
return atom_trace; | |
} | |
NIF_FUNCTION(enabled_send) | |
{ | |
+ // @todo Discard trace events for a percent of processes. | |
+ | |
+// if ((enif_hash(ERL_NIF_INTERNAL_HASH, argv[2], 0) % 100) > 10) | |
+// return atom_discard; | |
+ | |
// We always want both send and send_to_non_existing_process. | |
return atom_trace; | |
} | |
@@ -218,6 +241,8 @@ NIF_FUNCTION(trace) | |
// | |
// - {Tag, Tracee, Ts, Term} | |
// - {Tag, Tracee, Ts, Term, Extra} | |
+ // | |
+ // @todo The tag can probably be made an integer instead? | |
if (enif_get_map_value(env, argv[4], atom_extra, &extra)) | |
msg = enif_make_tuple5(env, argv[0], argv[2], ts, argv[3], extra); | |
diff --git a/test/lg_SUITE.erl b/test/lg_SUITE.erl | |
index 99e559c..ca0a69e 100644 | |
--- a/test/lg_SUITE.erl | |
+++ b/test/lg_SUITE.erl | |
@@ -76,8 +76,20 @@ running_true(Config) -> | |
send_true(Config) -> | |
doc("Trace a specific module with send option enabled."), | |
lg:trace(lists, lg_file_tracer, config(priv_dir, Config) ++ "/send_true.lz4", | |
- #{send => true}), | |
- lists:seq(1,10), | |
+ #{pool_size => 1, send => true}), | |
+ Self = self(), | |
+ %% Send a message to and from an existing process. | |
+ Pid = spawn(fun() -> | |
+ receive {msg_from, Self} -> | |
+ Self ! {msg_from, self()} | |
+ end | |
+ end), | |
+ Pid ! {msg_from, Self}, | |
+ receive {msg_from, Pid} -> ok end, | |
+ %% Also send a message to a non existing process. | |
+ DeadPid = spawn(fun() -> ok end), | |
+ receive after 100 -> ok end, | |
+ DeadPid ! {msg_from, Self}, | |
lg:stop(), | |
do_ensure_decompress(config(priv_dir, Config) ++ "/send_true.lz4"). | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%% Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. | |
%% | |
%% This package, Looking Glass, is double-licensed under the Mozilla | |
%% Public License 1.1 ("MPL") and the Apache License version 2 | |
%% ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL, | |
%% please see LICENSE-APACHE2. | |
%% | |
%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, | |
%% either express or implied. See the LICENSE file for specific language governing | |
%% rights and limitations of this software. | |
%% | |
%% If you have any questions regarding licensing, please contact us at | |
%% info@rabbitmq.com. | |
-module(lg_messages). | |
-export([profile/1]). | |
-export([profile_many/1]). | |
-record(state, { | |
processes = #{} :: #{pid() => pos_integer()}, | |
pairs = #{} :: #{{pid(), pid()} => pos_integer()}, | |
non_existing = #{} :: #{pid() => pos_integer()}, | |
calls = #{} :: #{pid() => atom()} | |
}). | |
-spec profile(file:filename_all()) -> ok. | |
profile(Input) -> | |
{ok, FinalState} = lg_file_reader:fold(fun handle_event/2, #state{}, Input), | |
flush(FinalState). | |
-spec profile_many(file:filename()) -> ok. | |
profile_many(Wildcard) -> | |
Files = filelib:wildcard(Wildcard), | |
FinalState = lists:foldl(fun(Input, State0) -> | |
{ok, State} = lg_file_reader:fold(fun handle_event/2, State0, Input), | |
State | |
end, #state{}, Files), | |
flush(FinalState). | |
%% @todo Later we may want to look at the latency of gen_server call/reply. | |
%% @todo Later we may want to look at particular messages, have some sort of callback. | |
handle_event({send, From, _, Msg, To}, State=#state{processes=Procs, pairs=Pairs, calls=Calls}) -> | |
ProcsCount = maps:get(From, Procs, 0), | |
PairsCount = maps:get({From, To}, Pairs, 0), | |
State#state{processes=Procs#{From => ProcsCount + 1}, | |
pairs=Pairs#{{From, To} => PairsCount + 1}, | |
calls=Calls#{From => Msg}}; | |
handle_event({send_to_non_existing_process, From, _, _, _}, | |
State=#state{non_existing=Map}) -> | |
Count = maps:get(From, Map, 0), | |
State#state{non_existing=Map#{From => Count + 1}}; | |
%% We save the most recent call for each process for identification. | |
%%handle_event({call, Pid, _, MFA}, State=#state{calls=Calls}) -> | |
%% Acc = maps:get(Pid, Calls, []), | |
%% State#state{calls=Calls#{Pid => [MFA|Acc]}}; | |
%% Ignore all other events. We only care about messages. | |
handle_event(_, State) -> | |
State. | |
%% Output of the profiling. | |
flush(State) -> | |
flush_most_active_processes(State), | |
flush_most_non_existing(State), | |
flush_most_active_pair_unidirectional(State), | |
flush_most_active_pair_bidirectional(State), | |
io:format("~n"), | |
ok. | |
flush_most_active_processes(State=#state{processes=Procs}) -> | |
L = lists:sublist( | |
lists:reverse(lists:keysort(2, maps:to_list(Procs))), | |
1, 100), | |
io:format("~nThey send the most messages:~n~n Pid Count Most recent call~n"), | |
_ = [io:format(" ~p ~p ~p~n", [P, C, mfa(P, State)]) || {P, C} <- L], | |
ok. | |
flush_most_non_existing(State=#state{non_existing=Procs}) -> | |
L = lists:sublist( | |
lists:reverse(lists:keysort(2, maps:to_list(Procs))), | |
1, 100), | |
io:format("~nThey send the most messages to dead processes:~n~n Pid Count Most recent call~n"), | |
_ = [io:format(" ~p ~p ~p~n", [P, C, mfa(P, State)]) || {P, C} <- L], | |
ok. | |
flush_most_active_pair_unidirectional(#state{pairs=Procs}) -> | |
L = lists:sublist( | |
lists:reverse(lists:keysort(2, maps:to_list(Procs))), | |
1, 100), | |
io:format("~nThey send the most messages to this other process:~n~n" | |
" From To Count~n"), | |
_ = [io:format(" ~p ~p ~p~n", [F, T, C]) || {{F, T}, C} <- L], | |
ok. | |
flush_most_active_pair_bidirectional(#state{pairs=Procs0}) -> | |
Procs = maps:fold(fun merge_pairs/3, #{}, Procs0), | |
L = lists:sublist( | |
lists:reverse(lists:keysort(2, maps:to_list(Procs))), | |
1, 100), | |
io:format("~nThey send the most messages to each other:~n~n" | |
" Pid 1 Pid 2 Count~n"), | |
_ = [io:format(" ~p ~p ~p~n", [F, T, C]) || {{F, T}, C} <- L], | |
ok. | |
mfa(Pid, #state{calls=Calls}) -> | |
%% @todo convert_mfa from lg_callgrind. | |
maps:get(Pid, Calls, 'No call recorded.'). | |
merge_pairs({From, To}, Count, Acc) -> | |
Key = if | |
From < To -> {From, To}; | |
true -> {To, From} | |
end, | |
AccCount = maps:get(Key, Acc, 0), | |
Acc#{Key => AccCount + Count}. | |
%% which process sends the most messages | |
%% which process sends the most messages to non existent processes | |
%% which p1->p2 sees the most activity | |
%% which p1->p2 + p2->p1 sees the most activity |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment