Re: Unboxed structures (yes, again, only this time for real)

"Yuri Davidovsky (as work at disclosure dot ie)" <[email protected]>
Newsgroups gmane.lisp.lispworks.general
Message-ID <[email protected]>
Not much luck with FLI, it can only accept typed arrays of fundamental types, however I found definite answers to the struct array allocation without it.

> On 16 Jan 2026, at 11:00, Tim Bradshaw <[email protected]> wrote:
> 
>> ;; Initialize array of particles
>> (defparameter *particles* (make-array +num-particles+ :element-type 'particle))
> 
> And now
> 
> ? (array-element-type *particles*)
> t

What I did was simply this: I took the note of the RAM usage in the activity monitor and then initialised the typed array first like so:

(defconstant +num-particles+ (* 10 1000 1000))
(defparameter *particles* (make-array +num-particles+ :element-type 'particle))

That is 10M particles. After making the array the memory usage went up by 80MB, which adds up for an array of 8 bytes per pointer times 10M. Hence we conclude with confidence that indeed the arrays in Common Lisp cannot be typed beyond the fundamental numeric types.

Afterwards I populated the array doing

(dotimes (i +num-particles+)
  (setf (aref *particles* i) 
        (make-particle :x (random 100.0) :y (random 100.0) 
                       :vel-x (random 5.0) :vel-y (random 5.0))))

and the RAM usage went by about 820MB which is roughly 10M x 80 bytes, hence these calculations appear to be correct:

> In particular the object size of a PARTICLE is 80 bytes, which is 8 64-bit fields and two words (16 bytes) of header.


Not sure what the header part is for, but the overall size appears to match Bradshaw’s predictions. In comparison, a 10M custom structs serialised array shows the expected 32 x 10M = 320MB after initialisation by 

(make-particle-set +num-particles+
                   :x (random 100.0)
                   :y (random 100.0)
                   :vel-x (random 5.0)
                   :vel-y (random 5.0)))

However I still have some questions:

1. How come the T array appeared to be the same speed as a continuous byte array with serialised structs in it?
2. What does “boxing” actually mean? Is it placing a value on the heap? Or is it simply bit tagging?
3. What is an “immediate value”? Is it a value that is not located on heap, while the pointer is still tagged?
4. Conversely, is a “raw” value the same as an “immediate” value but with the bit tag stripped out?
5. Which of the above 2-4 applies to what in the context of Common Lisp structures?

In relation to 1 I think possible answers could be:
1. Some prefetching optimisation by either compiler, or the OS (or the CPU). That would be nice as any free performance, but the bad aspect of it is that you do not know in what situations you can/cannot rely on it, it simply magically happens, or it magically does not happen.
2. The typed aref array access is slow. I specifically had qualms about this part:

(SYSTEM:TYPED-AREF 'SINGLE-FLOAT PARTICLES (+ (* I 32) 8))

Typically such access (stride * index + field-offset) should be free as CPUs have specific multiply-add instructions to make such addressing zero overhead, but I am not sure the expression gets detangled correctly here so instead we may have to do some additional calculations. It could be that this part was a computational overhead that slowed the serialised struct access down to about the same level as accessing the struct pointer array. 

I also might try using a single float typed array avoiding the casting using typed-aref part to see if that also could be the issue.

In relation to 2-5, what I am going to try is to find a way to serialise a vanilla struct verbatim and examine it somehow on the byte level but I am not sure if I will get myself together to do it at this stage, I spent way more time on it this week than I ever planned.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.