Elixir Garbage Collection
Garbage collection is the runtime reclaiming memory from values a process no longer uses. It runs on its own, and it can also be forced for one process.
Forcing a collection returns true
The current process asks for a collection. The answer is true.
IO.inspect(:erlang.garbage_collect(self()))
IO.inspect(:erlang.garbage_collect())A collected worker stays alive
A waiting worker is forced to collect. It stays alive until it gets its stop message.
parent = self()
worker = spawn(fn ->
send(parent, :ready)
receive do
:stop -> :ok
end
end)
receive do
:ready -> :ok
end
IO.inspect(:erlang.garbage_collect(worker))
IO.inspect(Process.alive?(worker))
ref = Process.monitor(worker)
send(worker, :stop)
receive do
{:DOWN, ^ref, :process, ^worker, :normal} -> :ok
endDropping a large value keeps the small one
A large list is replaced by a small list. The small list still has three items after a forced collection.
data = Enum.to_list(1..100)
IO.inspect(length(data))
data = [10, 20, 30]
IO.inspect(:erlang.garbage_collect(self()))
IO.inspect(length(data))Example
parent = self()
worker = spawn(fn ->
send(parent, :ready)
receive do
:stop -> :ok
end
end)
receive do
:ready -> :ok
end
IO.inspect(:erlang.garbage_collect(worker))
IO.inspect(Process.alive?(worker))
data = Enum.to_list(1..50)
IO.inspect(length(data))
data = [7, 8]
IO.inspect(:erlang.garbage_collect(self()))
IO.inspect(length(data))
ref = Process.monitor(worker)
send(worker, :stop)
receive do
{:DOWN, ^ref, :process, ^worker, :normal} -> :ok
endKey points
- Collection: :erlang.garbage_collect forces a collection for one process and returns true.
- Automatic: the runtime also collects on its own without being asked.
- Dropped value: rebinding a variable to a small value drops the old large value.
- Kept value: a value still named by a variable is kept, not collected.
- Worker collection: forcing a collection on a waiting worker leaves the worker alive.
- Use :erlang.garbage_collect to ask for a collection, never to measure memory.
In this example, a waiting worker is started, then a collection is forced on the worker, then the worker is shown alive, then a large list is built and its length is printed, then the list is replaced by a small list, then a collection is forced on the current process, then the small length is printed, and finally the worker is stopped.
Note
forcing a collection returns true even when there is nothing to reclaim.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does :erlang.garbage_collect return when it forces a collection?