memory usage by objects in common lisp

六月ゝ 毕业季﹏ 提交于 2019-12-01 17:29:16

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!