Skip to content

Commit bd30daa

Browse files
committed
do not duplicate child specs in different syn scopes
to decrease memory usage in ets, do not track twice the child specs in different scopes. This especially helps if the start data passed to start link is big
1 parent 2b541ae commit bd30daa

3 files changed

Lines changed: 47 additions & 17 deletions

File tree

lib/syn_supervisor.ex

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,11 @@ defmodule SynSupervisor do
784784
reply =
785785
state.scope
786786
|> Distribution.list_children()
787-
|> Enum.map(fn %Child{} = c ->
788-
{id, _, _, _, type, modules} = c.spec
789-
{id, c.pid, type, modules}
787+
|> Enum.flat_map(fn %Child{} = c ->
788+
case Distribution.spec_for_child(state.scope, c) do
789+
{:ok, {id, _, _, _, type, modules}} -> [{id, c.pid, type, modules}]
790+
_ -> []
791+
end
790792
end)
791793

792794
{:reply, reply, state}
@@ -832,9 +834,10 @@ defmodule SynSupervisor do
832834
{active, workers, supervisors} =
833835
Enum.reduce(children, {0, 0, 0}, fn
834836
%Child{} = c, {active, worker, supervisor} ->
835-
case c.spec do
836-
{_, _, _, _, :worker, _} -> {active + 1, worker + 1, supervisor}
837-
{_, _, _, _, :supervisor, _} -> {active + 1, worker, supervisor + 1}
837+
case Distribution.spec_for_child(state.scope, c) do
838+
{:ok, {_, _, _, _, :worker, _}} -> {active + 1, worker + 1, supervisor}
839+
{:ok, {_, _, _, _, :supervisor, _}} -> {active + 1, worker, supervisor + 1}
840+
_ -> {active, worker, supervisor}
838841
end
839842
end)
840843

@@ -854,10 +857,9 @@ defmodule SynSupervisor do
854857
# try local children anyway
855858
terminate_local_children(pid_or_child_id, state)
856859

857-
{:ok, %Child{node: node, supervisor_pid: supervisor} = c} ->
860+
{:ok, %Child{id: child_id, node: node, supervisor_pid: supervisor} = c} ->
858861
if node == Node.self() do
859-
Distribution.untrack_spec(state.scope, c.spec)
860-
terminate_local_children(c.pid, state)
862+
terminate_local_children_and_untrack_spec(c.pid, child_id, state)
861863
else
862864
terminate_remote_children(node, supervisor, c.pid, state)
863865
end
@@ -876,6 +878,17 @@ defmodule SynSupervisor do
876878
end
877879
end
878880

881+
defp terminate_local_children_and_untrack_spec(pid, child_id, state) do
882+
case terminate_local_children(pid, state) do
883+
{:reply, :ok, next_state} ->
884+
Distribution.untrack_spec(state.scope, child_id)
885+
{:reply, :ok, next_state}
886+
887+
reply ->
888+
reply
889+
end
890+
end
891+
879892
defp terminate_local_children(pid, %{children: children} = state) when is_pid(pid) do
880893
case children do
881894
%{^pid => info} ->
@@ -1170,13 +1183,23 @@ defmodule SynSupervisor do
11701183

11711184
defp maybe_start_child(%Child{} = c, assigned_node, _assigned_sup, state) do
11721185
if assigned_node == Node.self() and c.node != Node.self() do
1173-
{_, _, state} = start_local_child(c.spec, state)
1174-
state
1186+
find_spec_and_start_local_child(c.id, state)
11751187
else
11761188
state
11771189
end
11781190
end
11791191

1192+
def find_spec_and_start_local_child(child_id, state) do
1193+
case Distribution.find_spec(state.scope, child_id) do
1194+
{:ok, child_spec} ->
1195+
{_, _, state} = start_local_child(child_spec, state)
1196+
state
1197+
1198+
_ ->
1199+
state
1200+
end
1201+
end
1202+
11801203
defp monitor_children(children) do
11811204
Enum.reduce(children, {%{}, %{}, %{}}, fn
11821205
{_, {:restarting, _}}, acc ->

lib/syn_supervisor/distribution.ex

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ defmodule SynSupervisor.Distribution do
3535
id: id,
3636
node: node,
3737
pid: child_pid,
38-
spec: child_spec,
3938
supervisor_pid: supervisor
4039
}
4140

@@ -75,6 +74,11 @@ defmodule SynSupervisor.Distribution do
7574
end
7675
end
7776

77+
@spec spec_for_child(scope_t(), Child.t()) :: {:ok, Child.spec_t()} | {:error, :not_found}
78+
def spec_for_child(scope, %Child{} = c) do
79+
find_spec(scope, c.id)
80+
end
81+
7882
@spec list_children(scope_t()) :: list(Child.t())
7983
def list_children(scope) do
8084
scope
@@ -161,8 +165,12 @@ defmodule SynSupervisor.Distribution do
161165
|> Enum.map(&:syn.join(spec_scope(scope), child_id, &1, child_spec))
162166
end
163167

164-
@spec untrack_spec(scope_t(), Child.spec_t()) :: list(:ok | {:error, term()})
168+
@spec untrack_spec(scope_t(), Child.spec_t() | Child.id_t()) :: list(:ok | {:error, term()})
165169
def untrack_spec(scope, {child_id, _, _, _, _, _}) do
170+
untrack_spec(scope, child_id)
171+
end
172+
173+
def untrack_spec(scope, child_id) do
166174
scope
167175
|> supervisors()
168176
|> Enum.map(&:syn.leave(spec_scope(scope), child_id, &1))

lib/syn_supervisor/distribution/child.ex

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ defmodule SynSupervisor.Distribution.Child do
1010
id: id_t(),
1111
pid: pid(),
1212
node: Node.t(),
13-
supervisor_pid: pid(),
14-
spec: spec_t()
13+
supervisor_pid: pid()
1514
}
1615

17-
@enforce_keys [:id, :pid, :node, :supervisor_pid, :spec]
18-
defstruct [:id, :pid, :node, :supervisor_pid, :spec]
16+
@enforce_keys [:id, :pid, :node, :supervisor_pid]
17+
defstruct [:id, :pid, :node, :supervisor_pid]
1918
end

0 commit comments

Comments
 (0)