Is there a way to find out how much memory is used by an instance of a class or basic data types in general?
I have a toy webframework in cl that creates and manages web pages with instances of classes that represent the html tags and their properties, and as they are supposed to make an html page, they have children in a slot called children. so I was thinking how much a user's session will cost the server if I take this approach. Thanks.
As far as I know, there is nothing like this for arbitrary objects in the standard, but there are implementation-dependent solutions, like ccl:object-direct-size
in CCL:
CL-USER> (object-direct-size "foo")
16
However, be aware that whether these do what you want depends on what you mean by "size", since those functions usually don't include the size of the components the object references. You can also run the GC, initialize a few objects and compare room
's output before and afterwards.
Also, note that time
usually includes allocation information:
CL-USER> (time (length (make-array 100000)))
(LENGTH (MAKE-ARRAY 100000))
took 0 milliseconds (0.000 seconds) to run.
During that period, and with 2 available CPU cores,
0 milliseconds (0.000 seconds) were spent in user mode
0 milliseconds (0.000 seconds) were spent in system mode
400,040 bytes of memory allocated.
100000
Maybe you could try something like this (untested, really just a quick hack):
(defmethod size ((object standard-object))
(let ((size (ccl:object-direct-size object)))
(dolist (slot (mapcar #'ccl:slot-definition-name
(ccl:class-slots (class-of object))))
(when (slot-boundp object slot)
(incf size (size (slot-value object slot)))))
size))
(defmethod size ((list list))
(reduce (lambda (acc object) (+ acc (size object)))
list
:initial-value (ccl:object-direct-size list)))
(defmethod size (object)
(ccl:object-direct-size object))
For example:
CL-USER> (defclass foo ()
((child :accessor child :initarg :child)))
#<STANDARD-CLASS FOO>
CL-USER> (defclass bar (foo)
((child2 :accessor child2 :initarg :child2)))
#<STANDARD-CLASS BAR>
CL-USER> (size '())
0
CL-USER> (size "foo")
16
CL-USER> (size '("foo" "bar"))
40
CL-USER> (size (make-instance 'foo))
16
CL-USER> (size (make-instance 'foo :child '("foo" "bar" "baz")))
72
CL-USER> (size (make-instance
'bar
:child "foo"
:child2 (make-instance 'foo :child (make-array 100))))
456
In Common Lisp the CLOS objects usually are a collection of slots. Typically these slots might be internally stored in some kind of vector. CLOS slots typically will contain either a pointer to some data object or, for a few primitive datatypes, may include the data itself. These primitive data types have to fit into a memory word: examples are fixnums and characters. Common Lisp implementations typically don't inline more complex data structures into a slot. For example a slot could be declared to contain a vector of fixnums. Implementations would not allocate this vector inside the CLOS object. The CLOS object will point to a vector object.
The CLOS object itself should occupy then: number of slots * word size + overhead.
Let's assume a word is 4 bytes long, 32bit.
This might be the size for a CLOS object with ten slots:
10 slots * 4 bytes + 8 bytes = 48 bytes
Now imagine that each slot of a CLOS object points to a different string and each string is 100 bytes long.
Example from above:
1 CLOS object + 10 strings each 100 bytes.
48 bytes + 10 * 100 = 1048 bytes
Now imagine that each of the slot points to the same string:
1 CLOS object + 1 string of 100 bytes.
48 bytes + 100 bytes = 148 bytes
To calculate the size of a CLOS object you could either:
just count the size of the CLOS object itself. That's easy.
somehow calculate a graph of objects with are reachable from the object, determine the unique memory objects (minus direct allocated primitive objects) and sum all memory sizes of those.
I also have web framework in cl, also was struggling with same sessions problem and here is what universe sent to me https://people.gnome.org/~xan/memory.lisp
It seems to work in sbcl
(memory::dump-memory (weblocks::active-sessions))
Total memory used: 99.785706 MB