dsnipe

dsnipe

Memory leaking with long running processes

Hello.
I have an application in production under some load and it has a memory leak.
I’m preaty new in Erlang world, anyway I tried to debug it using recon library. And it looks like the problem is with binaries.
recon_alloc:memory(allocated_types) shows me that my binary_alloc and eheap_alloc increase all the time.
Tha application is quite simple.
At boot time my application loads some data from DB and run for each record a process (GenServer) with some state (not big). At one moment there might be from 1 to 10 such long running processes. I use Phoenix endpoints to listen HTTP requests and each go through all these long lived processes with request payload in format: %{"segments": [%{"some_var" => "some bn data"}]}. I suspect, that these binaries are not garbage collected, bevcause they still may have references from those long lived processes.
Migh be that a reason? And how to solve it?

Elixir 1.4, Erlang 19.3

Marked As Solved

sasajuric

sasajuric

Author of Elixir In Action

My advice is to simply give it a try and see how it fares. Adding hibernation is fairly trivial (just append :hibernate to each return tuple). And with hibernation in place you can quickly check whether the problem is fixed (if not, then the leak likely happens someplace else). If the hibernation is fast enough for you, than cool. If not, you’ll need to think of another way.

Also Liked

sasajuric

sasajuric

Author of Elixir In Action

That might indeed be a reason. A simple fix could be to hibernate each process after they do the work on the segment. So if it’s a GenServer, you can add :hibernate at the end of each tuple you return from handle_* callbacks (e.g. {:noreply, new_state, :hibernate}). This will lead to the GC of the GenServer and thus the references to binaries will be released.

Hibernation will cause some performance penalty, but whether that’s significant or not depends on the load on the process being hibernated.

Note that you can also use :recon.bin_leak/1 to try to find out the offending processes.

rvirding

rvirding

Creator of Erlang

It might be faster to just do a gc, :erlang.garbage_collect(), as doing a hibernate does more work because it first packs the process together then unpacks it on the next message. I don’t know if there is an Elixir call to this function.

NobbZ

NobbZ

Are you sure? AFAIK elixir can’t support OTP 16, since maps have only been introduced with OTP 17.

The README of the 1.4.0 tag of the github repository clearly states:

(Elixir requires Erlang 18.0 or later)

Also I think I’ve seen some kind of matrix once which desc ribed which version of erlang was supported by which version of elixir, but I can’t find it right now.


Aside of that, you can create space leaks (not memory leaks) easily when creating substrings from strings that are longer 64 byte. Therefore it is considered good practice to :binary.copy/1 strings you have extracted and want to use for longer than a few moments.

As a rule of thumb I do copy every string I pass into another function.

Where Next?

Popular in Questions Top

vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement