okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

Aly Raffaufperf(lcm): cut below-trigger payload decodes from O(n) to O(1)61dad0e

main
1.7 KiB38 linesraw
1%% Count payload decodes on the preparation caller without production metrics.
2-module(albedo_lcm_preparation_test_support).
3-export([count_decodes/2]).
4
5count_decodes(Owner, Run) ->
6    Processes = lists:usort([self(), Owner]),
7    Patterns = [{albedo_conversation, unpack, 2}, {albedo_conversation, unpack_fit, 2}],
8    Tracer = spawn(fun() -> collect(0, none) end),
9    lists:foreach(fun(Pattern) -> erlang:trace_pattern(Pattern, true, [local]) end, Patterns),
10    lists:foreach(fun(Pid) -> erlang:trace(Pid, true, [call, {tracer, Tracer}]) end, Processes),
11    try
12        Value = Run(),
13        Tracer ! {count, self(), Processes},
14        receive {decode_count, Count} -> {Value, Count} end
15    after
16        lists:foreach(fun(Pid) -> erlang:trace(Pid, false, [call]) end, Processes),
17        lists:foreach(fun(Pattern) -> erlang:trace_pattern(Pattern, false, [local]) end, Patterns),
18        exit(Tracer, kill)
19    end.
20
21%% The tracer drains its own delivery markers before answering. Keep call
22%% tracing enabled until the markers arrive, so queued events are retained.
23collect(Count, Finish) ->
24    receive
25        {trace, _, call, {albedo_conversation, Function, [_, _]}}
26                when Function =:= unpack; Function =:= unpack_fit ->
27            collect(Count + 1, Finish);
28        {count, Reply, Processes} ->
29            Refs = [erlang:trace_delivered(Pid) || Pid <- Processes],
30            collect(Count, {Reply, Refs});
31        {trace_delivered, _, Ref} ->
32            {Reply, Refs} = Finish,
33            case lists:delete(Ref, Refs) of
34                [] -> Reply ! {decode_count, Count}, collect(Count, none);
35                Pending -> collect(Count, {Reply, Pending})
36            end;
37        _ -> collect(Count, Finish)
38    end.