[Openmcl-devel] memory

Gary Byers gb at clozure.com
Tue Apr 13 18:41:39 PDT 2010

Saying "you don't understand much about the details of object
representation in CCL!" sounds a lot like someone saying "your martial
arts school teaches an unorthodox fighting style!" in a low-budget
Kung Fu movie; it soon becomes clear that the latter is intended to
provoke a violent referendum on the merits of orthodoxy, while the
former is intended as a simple observation.

You (Alex) don't understand much about the details of object
representation in CCL.  (Even if that's poorly lip-synched and the
subtitles are unreadable, that's not intended to be inflammatory:
there are probably only a handful of people who do understand those
details and not too many reasons for most people to want or need to
understand them.)

I don't have a strong opinion as to whether SIZEOF should be a generic
function or not; I do have trouble with the idea that it should return
random, incorrect values.  (That seems like an unorthodox fighting
style, now that I think about it.)

One aspect of a correct answer in CCL is that the size of any
heap-allocated lisp object is always a multiple of (* 2
target::node-size), where TARGET::NODE-SIZE is defined as 4 on
32-bit platforms and 8 in 64-bit CCL.  This means that 1,000,000
distinct empty strings ("") would require ~8MB or ~16MB to store
in memory, even though their total combined LENGTH is 0.  Recent
versions of HEAP-UTILIZATION show this distinction between the
logical size and physical size of things implemented as CCL::UVECTORs,
and show that the differences can add up.

CCL:UVSIZE is indeed a good way of determining the number of elements
in a CCL::UVECTOR; in fact, it's essentially the only way.  Determing
the logical size of a uvector involves knowing how many elements it
contains and what the size of each element is.  In a few cases, the
element size is constant accross all platforms (e.g. SIMPLE-STRINGs
always have 4-byte elements); in general, this devolves to platform-specific
code pretty quickly.  That code already exists in the platform/architecture-
specific parts of the compiler backend and the implementation of SIZEOF
that I wrote used that code; I did it that way because experience has
taught me that if I try to do it as a huge heavily-conditionalized CASE
statement or as a series or methods, I'll get it wrong or watch it
break when a new architecture is introduced.  It's really, really bad
to get this kind of stuff completely wrong, and it's really easy to get
it completely wrong.  (I've done so.  Often.)

If there are indeed reasons to want to make SIZEOF a generic function,
then I think that it'd be best to use the function that I wrote (or
something functionally equivalent) as the default method (specialized
on T) and to (carefully) fudge the value returned by CALL-NEXT-METHOD
in specialized methods if that's really necessary or desirable.
Otherwise, you run a real risk of winding up with things like:

(defmethod size-of ((thing fixnum))

That's meaningless: FIXNUMs aren't allocated in memory (and where on earth
did the number 4 come from ?)  Having done things every bit as stupid, I'm
not trying to incite a riot in calling that stupid.  (If I -was- trying
to incite a riot, I'd insult your martial arts school.)

On Tue, 13 Apr 2010, R. Matthew Emerson wrote:

> On Apr 13, 2010, at 11:07 AM, Alexander Repenning wrote:
>> On Apr 13, 2010, at 4:42 AM, Gary Byers wrote:
>>> The SIZEOF a SIMPLE-STRING is its length * 4, + the size of a header (4 bytes
>>> in 32-bit CCL, 8 bytes in 64-bit CCL), rounded up to an object alignment boundary
>>> (8/16 bytes.)  The SIZEOF function that I mailed out yesterday should know how
>>> compute this value.
>> uvsize is a pretty handy function to compute these kinds of sizes. Overall, I prefer sizeof to be a method in order to be able to compute sizes of custom types/classes. However, Your sizeof appears to return strange results for some simple types including floats, CCL32:
>> ? (sizeof 3.14)
>> 8
>> ;; should this not be 4
>> ? (type-of 3.14)
>> In CCL64 the result is 0 because single-floats are not uvectors and the case is not handled in your cond
> In a 32-bit ccl, a single-float is a uvector.  There is a 32-bit header, and another 32-bit word that contains the actual bits that represent the float.  That's where the answer of 8 bytes comes up.
> On a 64-bit ccl, a single float is an immediate quantity, like a fixnum or a character.  (The float bits are stored in the upper 4 bytes of a 64-bit word.)
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list