Handling low memory on server

I have in my application a few GenServers caching data which could eventually lead to out-of-memory errors.

Is there a low memory signal I could handle from my GenServer to let them free some memory?

How would you handle such a case?

If you want to hint GC run for given process then you can hibernate it when it is not doing stuff

Returning {:reply, reply, new_state, :hibernate} is similar to {:reply, reply, new_state} except the process is hibernated and will continue the loop once a message is in its message queue. However, if a message is already in the message queue, the process will continue the loop immediately. Hibernating a GenServer causes garbage collection and leaves a continuous heap that minimises the memory used by the process.

Via GenServer — Elixir v1.16.0

1 Like

You can check memory usage with memsup (and the get_system_memory_data/0 function).

2 Likes

Thanks!

I think I will make my GenServer periodically (with Process.send_after) check the BEAM memory usage and if required, flush the GenServer’s state (and maybe force a GC)

@hauleth thanks for the idea, but I don’t this fit my need. I want the GenServer to be always responsive, and just GarbageCollecting won’t be enough (its state takes a lot of memory)

After reading :os_mon and :memsup documentation, it’s even better than what I thought!

We can register alarm handlers that will be triggered when a custom memory threshold is reached. I’ll post my code here when I get it working.

4 Likes

The only problem is that the minimum interval for checking memory seems to be one minute.

disksup (also part of os_mon) supports smaller time interval since recently, I guess a patch to have the same feature for memsup would make sense.

If you need to check more often then you can use memsup:get_system_memory_data/0 (example here).

2 Likes