Fl4m3Ph03n1x

Fl4m3Ph03n1x

Get machine memory in elixir/erlang

Background

I have a module that saves data into an ETS without ever releasing it. Obviously, this is is a terrible idea. If you are not sure why, just ask yourself what happens when the machine no longer has memory to store data :smiley:

Solution

The obvious solution would be to periodically clean the data from the table, but I have orders to not do it, it has been decided another process in another application will do it. This process doesn’t exist yet and may never even exist, depending on who implements the other application.

Since I can’t rely on this, I decided to add a fallback mechanism. Dam’s have a fallback mechanism for excess water to flow, Nuclear Reactors have a mechanism for sea water to enter the reactors and cool them down (and then they release the heated, radioactive water back to the sea), so it only makes sense that if I want to build a reliable system, instead of waiting for the machine to crash catastrophically and restart, I should follow the example of such systems and decide what to do in case the system faces load it can’t cope with.

I decided I want to ditch requests upon a certain memory usage threshold. Let’s say, if the machine has 10GB of memory and BEAM is using 9GB already, I want to stop saving data into my ETS table.

Problem

To implement said solution, I made some research and found :memsup:

So, I rushed to open a iex terminal and test it out. But I can’t.

:memsup.start_link()
{:ok, #PID<0.142.0>}
iex(3)> [os_mon] memory supervisor port (memsup): Erlang has closed

16:17:12.618 [error] GenServer :memsup terminating
** (ArgumentError) argument error
    (stdlib) gen_event.erl:269: :gen_event.send/2
    memsup.erl:994: :memsup.set_alarm/2
    memsup.erl:375: :memsup.handle_info/2
    (stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:711: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:collected_sys, {7173283840, 8235118592}}
State: {:state, {:unix, :linux}, true, :undefined, :undefined, false, 60000, 30000, 0.8, 0.05, #PID<0.143.0>, #Reference<0.2483620304.3371171843.48667>, :undefined, [:reg], []}
** (EXIT from #PID<0.136.0>) shell process exited with reason: an exception was raised:
    ** (ArgumentError) argument error
        (stdlib) gen_event.erl:269: :gen_event.send/2
        memsup.erl:994: :memsup.set_alarm/2
        memsup.erl:375: :memsup.handle_info/2
        (stdlib) gen_server.erl:637: :gen_server.try_dispatch/4
        (stdlib) gen_server.erl:711: :gen_server.handle_msg/6
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

I get this cryptic error when trying to start_link the process so I can use it. What am I doing wrong?

Extra

I know that comparing BEAM’s total memory usage against the machine’s memory usage is not perfect, processes or atoms could be taking 99% of the used memory and I would still punish the ets tables. However, I still think this would make sense, since if that is the problem, I still don’t want my ETS tables to save anything until the issue is solved.

Marked As Solved

josevalim

josevalim

Creator of Elixir

You shouldn’t start it directly. You should start the :os_mon application which will start it for you. Generally speaking, always make sure to start an application before invoking any of its modules:

iex(2)> Application.ensure_all_started(:os_mon)
{:ok, [:sasl, :os_mon]}
iex(3)> :memsup.get_system_memory_data
[
  total_memory: 12652220416,
  free_memory: 23302144,
  system_total_memory: 12652220416
]

Also Liked

Fl4m3Ph03n1x

Fl4m3Ph03n1x

So I need to add :os_mon to:

def application do
    [
      extra_applications: [:logger, :runtime_tools, :os_mon],
      mod: {MyApp.Application, []}
    ]
end

In the mix.exs file, right ?

josevalim

josevalim

Creator of Elixir

Yes!!!

Fl4m3Ph03n1x

Fl4m3Ph03n1x

Thanks !

Where Next?

Popular in Questions Top

pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
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
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New

We're in Beta

About us Mission Statement