[erlang-questions] Why Beam.smp crashes when memory is over?

Richard O'Keefe <>
Tue Nov 10 22:52:07 CET 2009


On Nov 11, 2009, at 1:10 AM, Ulf Wiger wrote:
>
> In short, I can see a need for such limits, and would like to include
> a reduction ceiling. The limits could be set after careful testing
> and high enough that they protect against runaway processes. A  
> reduction
> limit could be checked at the end of each slice, perhaps.
>
> In my experience, per-process memory usage is fairly predictable in
> erlang. Does anyone have a different experience?

I am not denying the *need* for limits.  (Anyone else remember "engines"
in Scheme?)  I've had enough functions in enough languages go into
infinite recursion that I can see the point of stopping them.

However, Ulf Wiger has not addressed these points:

  - if the tagging scheme is changed (and it has in the past),
    memory requirements may change.  They may either decrease
    (if, say, a special tag for 2-element tuples were introduced)
    or increase (if, say, list cells were made bigger).

    In particular, you may recall an EEP from me suggesting that
    there should be two representations for atoms:  one physically
    unique as now and the other only logically unique as in LOGIX.
    There are three aims in that proposal:  (1) reduce the need for
    symbol table locking when creating atoms, (2) reduce the impact
    of the symbol table size limit by making it possible for a
    process to create as many LOGIX-type atoms as it wants, and (3)
    make it possible to garbage-collect such atoms.

    If a process creates an atom now, the atom goes in shared storage
    and presumably is not "billed to" that process.  With the
    LOGIX-style atoms proposal, many atoms would remain in the
    process's private heap and _would_ be billed to that process.

    If memory serves me correctly, the representation of binaries has
    changed in the past.  There are certainly thresholds in binaries;
    as the performance characteristics of processors and the abilities
    of the Erlang compiler and HiPE change, they might well change,
    and if they do, the space needs of processes using binaries change.

  - if a data structure library changes its representation,
    memory requirements may change.  One of the advantages of using
    a library is NOT having to know how it works inside.  Suppose
    I need to keep track of N accounts.  If I use gb_sets, from
    having looked at the source code I can tell that it will take
    something like 4N or 5N words, but without looking at the
    code, I would not know that.  Looking at the code NOW tells me
    what the space cost is NOW.  It does NOT guarantee me that the
    same space cost will apply in the next release.  I can think
    of plausible reasons why the space cost might go up and plausible
    reasons why it might go down.

  - switching from one library module to another may change the
    space needs.  For example, gb_sets and sets offer very similar
    interfaces.  gb_sets uses binary search, sets uses hashing.
    In the course of maintenance, you might very well want to change
    from one to another.  I haven't the faintest idea how much space
    N items in a sets: set would take, especially as there are
    tuning parameters in sets.erl which could very well be changed.

    It's fatally easy, when doing such maintenance, to forget to
    maintain the space bounds as well.

  - there are library modules where I have no idea how much space
    is needed.  Come to think of it, that's nearly all of them.
    I certainly haven't the least notion what the space costs of
    'supervisor' are.  I've just assumed that they were small enough
    that I didn't need to bother.

  - Erlang data structures are made of things whose size is naturally
    measured in bytes (binaries) and things whose size is naturally
    measured in words (list cells, tuples), and other stuff which I'll
    ignore.  When you switch from a 32-bit machine to a 64-bit machine
    (or vice versa) the size of *words* changes, but the size of
    *bytes* does not.  This means that *right now* if you want your
    size bounds to port between 32-bit and 64-bit machines, even
    assuming everything else to remain unaltered, your size bounds
    *must* be expressed as B*bytes + W*words, not as bytes nor as words
    alone.

Now it's open to someone to propose that space bounds (stack, heap,
mailbox, individual messages sent, ...) *should* be expressed as
{B,W} pairs, and such a proposal will get a respectful hearing from
me.

At any rate, I am not saying that space limits are an essentially
bad idea, or that some means of providing such limits shouldn't be
added to Erlang.  What I'm saying is that
   - GETTING the limits right is never going to be easy
   - KEEPING the limits right is never going to be easy
   - EXPLAINING how to determine appropriate limits in fairly simple
     terms is going to be a very important part of Erlang documentation
   - CHECKING the limits, perhaps with some sort of load testing tools,
     is going to become an important part of development and  
maintenance.



More information about the erlang-questions mailing list