memory-leakselixirworkererlang-otpets

Will ets table release memory after recreating with the same name?


I have genserver that aggregates events:

  def init(opts) do
    cache = :ets.new(:events_cache, [:set])
    {:ok, cache}
  end

  def handle_info(:autoflush, cache) do
    Logger.debug(fn -> "#{:ets.info(cache)[:size]} events was aggregated. Sending to transport..." end)
    Events.emit(:ets.tab2list(cache))
    Process.send_after(self(), :autoflush, @flush_after)
    {:noreply, :ets.new(:events_cache, [:set])}
  end

  def handle_cast({:add_event, event}, cache) do
    :ets.insert(cache, {event})
    {:noreply, cache}
  end

In init I create ets table. Add values in cast and flush data to external call in info cleaning memory of ets table(as I think).

Questions:

  1. Is this implementation prone to memory leak? Is old ets table garbage collected?
  2. Aside question: Does this implementation look sanely at all?

Solution

  • When you are creating an ETS table without a registered name (check the option named_table) the table is created with a reference. No matter how many you create, the old ones are still there so, yes, you have a leak of memory if you are not deleting the old ones.

    One way to avoid this is by using the named_table option. This is crashing if the previous table exists. You can put the creation of the table with a catch or inside a try-catch block.