Skip to content

Instantly share code, notes, and snippets.

@nickva
Created March 22, 2022 14:46
Show Gist options
  • Select an option

  • Save nickva/a5d8ce1ccab4c2dfdb115001da03c5f5 to your computer and use it in GitHub Desktop.

Select an option

Save nickva/a5d8ce1ccab4c2dfdb115001da03c5f5 to your computer and use it in GitHub Desktop.
-module(slow_tuples).
-export([
run/0
]).
run() ->
run(7500, 0.0008, {1647,841737,351137}).
run(Depth, BranchChance, Seed) ->
Trees = gen_trees(Depth, BranchChance, Seed),
erlang:garbage_collect(),
MPid = spawn_mem_sampler(self(), 500),
T1 = erlang:monotonic_time(),
[{VDepth, Tree}] = Trees,
stem_tree(VDepth, Tree, 1000, sets:new()),
T2 = erlang:monotonic_time(),
Max = get_max_mem(MPid),
erlang:garbage_collect(),
unlink(MPid),
exit(MPid, kill),
{deltaT(T2, T1), Max}.
stem_tree(_Depth, {Key, _, []} = Leaf, Limit, Seen) ->
{sets:add_element(Key, Seen), Limit - 1, Leaf, []};
stem_tree(Depth, {Key, _, Children}, Limit, Seen0) ->
Seen1 = sets:add_element(Key, Seen0),
lists:foldl(fun(Child, Acc) ->
{SeenAcc, LimitPosAcc, ChildAcc, BranchAcc} = Acc,
case stem_tree(Depth + 1, Child, Limit, SeenAcc) of
{NewSeenAcc, _, _, _} ->
{NewSeenAcc, LimitPosAcc, ChildAcc, BranchAcc};
{NewSeenAcc, _, _} ->
{NewSeenAcc, LimitPosAcc, ChildAcc, BranchAcc};
Else ->
erlang:error(Else)
end
end, {Seen1, -1, [], []}, Children).
gen_trees(Depth, BranchChance, Seed) ->
rand:seed(exrop, Seed),
[{1, node(Depth, BranchChance)}].
node(0, _) ->
{rev(), x, []};
node(Depth, BranchChance) ->
case rand:uniform() < BranchChance of
true ->
{rev(), x, [
node(Depth - 1, BranchChance),
node(Depth - 1, BranchChance)
]};
false ->
{rev(), x, [node(Depth - 1, BranchChance)]}
end.
rev() ->
term_to_binary(rand:uniform()).
deltaT(T0, T1) ->
erlang:convert_time_unit(T0 - T1, native, second).
spawn_mem_sampler(Pid, DtMsec) ->
spawn_link(fun() -> mem_sampler(Pid, DtMsec, mem_mb(Pid)) end).
mem_sampler(Pid, DtMsec, Max0) ->
timer:sleep(DtMsec),
Max = max(mem_mb(Pid), Max0),
receive
{get_mem, From} ->
From ! {mem_max, Max}
after 0 ->
ok
end,
mem_sampler(Pid, DtMsec, Max).
mem_mb(Pid) ->
{memory, Words} = erlang:process_info(Pid, memory),
Bytes = Words * 8,
Bytes / (1024 * 1024).
get_max_mem(Pid) ->
Pid ! {get_mem, self()},
receive {mem_max, Max} -> Max end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment