BAR
BAR

Reputation: 17071

ERlang HEAP overflow

I have quite a program..

Its almost complete..

However I am seeing a heap crash after about 12 hours of running.

I remember hearing that you can't program erlang in a certain way if not when you recurse the stack builds up. Can anyone provide an example of that??

And also is there any way to have a realtime monitor of what process' are stacking up?

Regards

EDIT - What about

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();

     _ -> continue
  end,
  loop().

Upvotes: 1

Views: 511

Answers (3)

I GIVE TERRIBLE ADVICE
I GIVE TERRIBLE ADVICE

Reputation: 9648

Even your edit is not tail-recursive:

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();
      _ -> continue 
  end,
  loop().

The order of execution for one function is: receive ... end, loop(). Now, if you get a {sys, _} message, loop/0 will be called from within the receive, transforming the order of execution above into something equivalent to:

 loop() ->
      receive
          loop() ->
               receive
                  ...
               end,
               loop(),
      end,
      loop() ->
         ...

The problem is that if you call loop() from within the receive, the VM still has to store the return point in order to run the loop() in place after the receive.

To make your function tail-recursive, you would need to do either:

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg);
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply;
      _ -> continue 
  end,
  loop().

or

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop();
      _ -> loop()
  end.

Where calling loop() really is always the last thing to be done in the function.

Upvotes: 8

Lukas
Lukas

Reputation: 5327

Something like this could be used for monitoring the current heap usage of processes in you system. Just put it in a printout in a looping gen_server or just run it in the shell every once in a while.

lists:reverse(lists:keysort(2,
   [{Pid,catch element(2,process_info(Pid,total_heap_size))} || Pid <- processes()])).

Upvotes: 1

din
din

Reputation: 21

The process loop must be tail-recursive.

DO NOT

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop()
  end,
  io:format("Message is processed~n", []).

See: http://www.erlang.org/doc/efficiency_guide/processes.html

Upvotes: 2

Related Questions