Packages

Erlang/Elixir's missing fast / functional data structures

Current section

Files

Jump to
fds src fds_util.erl
Raw

src/fds_util.erl

-module(fds_util).
-export([term_size/1]).
%% function to get the term size of ... a term.
%%
%% This does NOT include
%% * the size of atom data in the atom table,
%% * the true size of a binary as a binary can have 3-6 bytes of overhead, and refer to another, uncopied binary
%% * the true size of a large (>32 entry) map, as it is probabilistic. It instead reports the lower bound
%% * the size of the erlang process context that a PID points to
%% * the size of the erlang port context that a Port points to
%% * the size of the erlang node context that a Reference points to
%% * the true size of a fun, as the overhead can range from 9-13 words, and there is no way to measure the size of the environment
%% * the size of an ets table overhead / entry
term_size(Term) -> term_words(Term) * erlang:system_info({wordsize, external}).
term_words(Term) when is_integer(Term) -> 1;
%% TODO: large integers
term_words(Term) when is_atom(Term) -> 1;
term_words(Term) when is_float(Term) ->
case erlang:system_info(wordsize) of
4 -> 4;
8 -> 3
end;
term_words(Term) when is_binary(Term) -> 3 + byte_size(Term);
term_words([]) -> 1;
term_words([Term|Rest]) -> 1 + term_words(Term) + term_words(Rest);
term_words(Term) when is_tuple(Term) ->
2 + lists:sum([ term_words(element(Pos, Term)) || Pos <- lists:seq(1, tuple_size(Term))]);
term_words(Term) when is_map(Term) andalso map_size(Term) =< 32 ->
maps:fold(fun(Key, Value, TotalWords) -> TotalWords + term_words(Key) + term_words(Value) end, 5, Term);
term_words(Term) when is_map(Term) andalso map_size(Term) =< 32 ->
maps:fold(fun(Key, Value, TotalWords) -> TotalWords + term_words(Key) + term_words(Value) end, round(map_size(Term) * 1.6), Term);
term_words(Term) when is_pid(Term) orelse is_port(Term) ->
Local = node(),
case node(Term) of
Local -> 1;
_Remote -> 6
end;
term_words(Term) when is_reference(Term) ->
Local = node(),
case {node(Term), erlang:system_info(wordsize)} of
{Local, 4} -> 5;
{_Remote, 4} -> 12;
{Local, 8} -> 4;
{_Remote, 8} -> 10
end;
term_words(Term) when is_function(Term) ->
9.