Much higher memory consumption in Elixir 1.4

Hi everyone.

My app stayed in Elixir 1.3.4 for quite awhile and it worked fine. When I upgrade it to 1.4.0 / 1.4.1 / 1.4.2, it takes significantly more memory (and eventually crashes the Heroku dyno) when processing a JSON file around 40mb – the memory consumption keeps growing while processing and goes over 2gb.

I’ve tried to upgrade the poison from 2.x to 3.x but it doesn’t resolve the problem. I suspect there is some sort of optimization in string handling in Elixir 1.4.

Any advice or suggestion to help investigation is appreciated.

5 Likes

It would be very hard to say without seeing any code. Assuming that you only upgraded Elixir and no dependencies we can look at the changelogs for Elixir 1.4.* [1] and the only significant String changes seems to be an upgrade to support Unicode 9.0 which included some implementation changes but shouldn’t affect performance.

[1] https://github.com/elixir-lang/elixir/releases

2 Likes

How did you ugrade? Is your Elixir and Erlang binaries being compiled from source?

1 Like

The last line my code hit before the crash is:

 Poison.decode(payload)

where payload is the JSON binary. I tried using Poison 2.2.0 or 3.1.0 but both crashed at decode due to high memory consumption when I switched to Elixir 1.4.x.

1 Like

I’m not sure how to answer the question, I’m using Heroku Elixir buildpack for the deployment.

2 Likes

It’s kind of hard to say from this description. Is Elixir version the only thing that has changed, or are there some other changes as well (modifications in your code, upgraded libraries, BEAM installation)? Is JSON decoding the only thing being done, or is something else happening concurrently?

One way to pursue this is to try to reproduce it locally. You could start by checking how your system behaves locally when decoding the large JSON. If you can reproduce it locally, you could start the observer, find which processes are consuming most memory, and see what are they doing.

If you can indeed prove that Poison decoding is consuming much more memory on 1.4, compared to 1.3, then it might help if you provide a simple standalone example demonstrating the issue.

1 Like

Thank you for all inputs. I think I’ve identified the issue in my bad code now.

I see at one point I’ve the line:

Logger.debug ["Content:", inspect(content)]

which the content is the ~40mb string.

I’ve no idea why it didn’t draw that much of memory in Elixir 1.3, but removing that line and upgrade to Elixir 1.4 seems working fine – the app doesn’t go over a few hundred mb of memory in :observer.start graph.

2 Likes