Subject: Re: Allocation Problems
From: Erik Naggum <clerik@naggum.no>
Date: 1997/10/14
Newsgroups: comp.lang.lisp.franz,comp.lang.lisp
Message-ID: <3085831789285377@naggum.no>


* Chris Stolpe
| I only have 24M of ram and 64M of swap so I would expect it to fail if it
| tried to allocate 64M of memory. What I don't understand is why I'm
| getting different allocation request amounts for the same array or why a
| request for 64000016 bytes would cause a need for 170983234 bytes of
| heap.

Allegro CL uses a generational, copying garbage collector.  this is fast
and convenient, but uses twice the memory required by new objects.  here's
the output from `(room)' at startup in my somewhat tweaked Lisp image:

area  address(bytes)        cons        symbols        other bytes
                        8 bytes each  24 bytes each
                        (free:used)   (free:used)      (free:used)
Top #x596000
New #x52e000(425984)      180:4915      252:2         228384:97032
New #x4c6000(425984)       -----         -----            -----
Old #x102f50(3944624)     813:160189    218:21817        872:2110616
Root pages: 46
4608 (#x1200) bytes used for loading foreign functions
Reserved foreign function space at #x82000:
  262144 bytes allocated, 4608 bytes used (257536 bytes free)

the "new" space is occupied by objects that were allocated more recently
than the tenure-limit, which is measured in the number of gc's.  the "old"
space is occupied by tenured objects.  old space is not gc'ed as often as
new space.  (it is called a "global gc" if old space is included.)

because the garbage collector is copying between two spaces, only one of
the newspaces is in use at any given time.  this means that you can't
allocate very large objects in newspace, and it is usually a bad idea,
anyway, if you know they're going to hang around for a while.  Allegro
offers the ability to communicate your intent to the allocator:

(make-array '(3000 3000) :element-type '(unsigned-byte 8)
			 :initial-element 0
                         #+allegro :allocation #+allegro :old)

the `element-type' argument can take any of a number of useful values to
request specialized array and therefore smaller allocated objects:

    bit
    character
    fixnum
    single-float
    double-float
    (unsigned-byte 8)
    (unsigned-byte 16)
    (unsigned-byte 32)
    (signed-byte 8)
    (signed-byte 16)
    (signed-byte 32)
    (complex single-float)
    (complex double-float)

the above call to make-array consumes just over 9 million bytes of memory,
assuming that 8 bits per pixel is enough.

| Is there a way to determine the amount of space a variable is consuming?

er, "variable" is not quite what you think it is.  a _symbol_ takes up a
constant 24 bytes, as you can see from the above output from (room), but
the _values_ of the various slots take up more space.  there is no way (I
know of) to ask for the size of Lisp objects that don't have constant size,
but evaluate (room t) and learn more.

| How about a way to free allocated memory?  After the first attempt the cl
| image grew to 64M and didn't shrink when I set image to nil.

this is actually covered quite well in the User Guide, Chapter 15.  the
function sys:resize-areas is very good at reducing the size of the Lisp
process once you have unintentionally blown away your system memory.

#\Erik
-- 
if you think this year is "97", _you_ are not "year 2000 compliant".

see http://www.naggum.no/emacs/ for Emacs-20-related material.