Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Polvorin <pablo.polvorin@process-one.net>2010-09-10 22:32:19 +0400
committerPablo Polvorin <pablo.polvorin@process-one.net>2010-09-10 22:32:19 +0400
commit0d5f20cae1be1ba37ebb443741c8fa6e477ef1e4 (patch)
treefbb16eeae64f149d8caf29082464a5c127e16b48 /src/ejabberd_c2s.erl
parent77d5eabd0042cf6d8830bc85c1cbd86d6aaf3e6a (diff)
Include roster pack patch from Geoff
Patch was already applied to 2.x branch, but not yet ported to master.
Diffstat (limited to 'src/ejabberd_c2s.erl')
-rw-r--r--src/ejabberd_c2s.erl67
1 files changed, 65 insertions, 2 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 309287721..0a3cfe6b5 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -286,7 +286,8 @@ init([StateName, StateData, _FSMLimitOpts]) ->
NewStateData = StateData#state{sid = SID, socket_monitor = MRef},
{ok, StateName, NewStateData};
true ->
- {ok, StateName, StateData#state{socket_monitor = MRef}}
+ %% pack, as sharing is not preserved accross message passing
+ {ok, StateName, pack(StateData#state{socket_monitor = MRef})}
end.
%% Return list of all available resources of contacts,
@@ -2148,11 +2149,22 @@ maybe_migrate(StateName, StateData) ->
After = ejabberd_cluster:rehash_timeout(),
migrate(self(), NewNode, After)
end,
- fsm_next_state(StateName, StateData);
+ fsm_next_state_pack(StateName, StateData);
Node ->
fsm_migrate(StateName, StateData, Node, 0)
end.
+%% fsm_next_state_pack: Pack the StateData structure to improve
+%% sharing.
+fsm_next_state_pack(StateName, StateData) ->
+ fsm_next_state_gc(StateName, pack(StateData)).
+
+%% fsm_next_state_gc: Garbage collect the process heap to make use of
+%% the newly packed StateData structure.
+fsm_next_state_gc(StateName, PackedStateData) ->
+ erlang:garbage_collect(),
+ fsm_next_state(StateName, PackedStateData).
+
%% fsm_next_state: Generate the next_state FSM tuple with different
%% timeout, depending on the future state
fsm_next_state(session_established, StateData) ->
@@ -2231,3 +2243,54 @@ bounce_messages() ->
after 0 ->
ok
end.
+
+
+
+%%%----------------------------------------------------------------------
+%%% JID Set memory footprint reduction code
+%%%----------------------------------------------------------------------
+
+%% 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.