Skip to content

Instantly share code, notes, and snippets.

@erszcz
Last active August 29, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erszcz/8781993 to your computer and use it in GitHub Desktop.
Save erszcz/8781993 to your computer and use it in GitHub Desktop.
pack jids
-module(pack).
-compile([export_all]).
-define(SETS, gb_sets).
-define(DICT, dict).
-record(state, {pres_t = ?SETS:new(),
pres_f = ?SETS:new(),
pres_a = ?SETS:new(),
pres_i = ?SETS:new()}).
%% Try to reduce the heap footprint of the four presence sets
%% by ensuring that we re-use strings and Jids wherever possible.
pack(S = #state{pres_a=A,
pres_i=I,
pres_f=F,
pres_t=T}) ->
{NewA, Pack1} = pack_jid_set(A, gb_trees:empty()),
{NewI, Pack2} = pack_jid_set(I, Pack1),
{NewF, Pack3} = pack_jid_set(F, Pack2),
{NewT, _Pack4} = pack_jid_set(T, Pack3),
%% Throw away Pack4 so that if we delete references to
%% Strings or Jids in any of the sets there will be
%% no live references for the GC to find.
S#state{pres_a=NewA,
pres_i=NewI,
pres_f=NewF,
pres_t=NewT}.
pack_jid_set(Set, Pack) ->
Jids = ?SETS:to_list(Set),
{PackedJids, NewPack} = pack_jids(Jids, Pack, []),
{?SETS:from_list(PackedJids), NewPack}.
pack_jids([], Pack, Acc) -> {Acc, Pack};
pack_jids([{U,S,R}=Jid | Jids], Pack, Acc) ->
case gb_trees:lookup(Jid, Pack) of
{value, PackedJid} ->
pack_jids(Jids, Pack, [PackedJid | Acc]);
none ->
{NewU, Pack1} = pack_string(U, Pack),
{NewS, Pack2} = pack_string(S, Pack1),
{NewR, Pack3} = pack_string(R, Pack2),
NewJid = {NewU, NewS, NewR},
NewPack = gb_trees:insert(NewJid, NewJid, Pack3),
pack_jids(Jids, NewPack, [NewJid | Acc])
end.
pack_string(String, Pack) ->
case gb_trees:lookup(String, Pack) of
{value, PackedString} ->
{PackedString, Pack};
none ->
{String, gb_trees:insert(String, String, Pack)}
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment