Skip to content

Instantly share code, notes, and snippets.

@dominicletz
Created June 2, 2020 16:21
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dominicletz/615e4b89b9e6f2059b2520ed9adac5dc to your computer and use it in GitHub Desktop.
Save dominicletz/615e4b89b9e6f2059b2520ed9adac5dc to your computer and use it in GitHub Desktop.
Erlang script to show used vs. allocated carrier sizes to find impact of memory fragmentation
f().
Str = fun(X) -> io_lib:format("~p", [X]) end.
Percent = fun
(A, 0) -> "100%";
(A, B) -> [Str(round(100*A/B)), "%"]
end.
Get = fun
(undefined, _Key) -> 0;
(Info, Key) ->
element(2, lists:keyfind(Key, 1, Info))
end.
GetAlloc = fun
(undefined) -> 0;
(List) -> element(3, hd(List))
end.
Allocators = [sys_alloc, temp_alloc, sl_alloc, std_alloc, ll_alloc,
eheap_alloc, ets_alloc, fix_alloc, literal_alloc, exec_alloc,
binary_alloc, driver_alloc, mseg_alloc].
lists:foreach(fun(Alloc) ->
Info = (catch erlang:system_info({allocator, Alloc})),
if is_list(Info) ->
{Allocated, Used, Calls} = lists:foldl(
fun({instance, _Nr, Stats}, {Al, Us, Ca}) ->
Mbcs = proplists:get_value(mbcs, Stats),
Allocated = Get(Mbcs, carriers_size),
Used = case lists:keyfind(blocks, 1, proplists:get_value(mbcs, Stats, [])) of
false -> Get(Mbcs, blocks_size);
{blocks, _, _, _} -> Get(Mbcs, blocks_size);
{blocks, List} -> lists:foldl(fun({_, Other}, Sum) -> Sum + Get(Other, size) end, 0, List)
end,
Calls = GetAlloc(proplists:get_value(calls, Stats)),
{Allocated + Al, Used + Us, Calls + Ca};
(_, {Al, Us, Ca}) -> {Al, Us, Ca}
end,
{0, 0, 0},
Info
),
Waste = Allocated - Used,
io:format(
"~-14s got ~10s used of ~10s alloc (~4s) = ~10s waste @ ~10s calls~n",
[Alloc, Str(Used), Str(Allocated), Percent(Used, Allocated), Str(Waste), Str(Calls)]
);
true ->
io:format("~-14s is disabled~n", [Alloc])
end
end, Allocators).
@dominicletz
Copy link
Author

This will produce something like below. In this case showing that eheap_alloc wasted 7gb in unused carrier allocation and binary_alloc 300mb in unused carrier_allocation:

%~  sys_alloc    got          0 used of          0 alloc (100%) =          0 waste @          0 calls
%~  temp_alloc   got          0 used of     393216 alloc (  0%) =     393216 waste @    3755545 calls
%~  sl_alloc     got        680 used of     196608 alloc (  0%) =     195928 waste @    1197199 calls
%~  std_alloc    got     278200 used of    3342336 alloc (  8%) =    3064136 waste @      72962 calls
%~  ll_alloc     got   27332880 used of   44040192 alloc ( 62%) =   16707312 waste @      48529 calls
%~  eheap_alloc  got  264987872 used of 7334526976 alloc (  4%) = 7069539104 waste @    5950303 calls
%~  ets_alloc    got  371648872 used of  547553280 alloc ( 68%) =  175904408 waste @    2656769 calls
%~  fix_alloc    got    1272928 used of    3342336 alloc ( 38%) =    2069408 waste @    4390573 calls
%~  literal_allo got    2765352 used of    4194304 alloc ( 66%) =    1428952 waste @        778 calls
%~  exec_alloc   got          0 used of          0 alloc (100%) =          0 waste @          0 calls
%~  binary_alloc got   80217512 used of  380829696 alloc ( 21%) =  300612184 waste @  898306924 calls
%~  driver_alloc got     169960 used of    5439488 alloc (  3%) =    5269528 waste @    7938628 calls
%~  mseg_alloc   got          0 used of          0 alloc (100%) =          0 waste @          0 calls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment