memory usage by objects in common lisp

后端 未结 3 1895
伪装坚强ぢ
伪装坚强ぢ 2021-01-18 01:15

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 manage

相关标签:
3条回答
  • 2021-01-18 01:54

    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.

    0 讨论(0)
  • 2021-01-18 02:00

    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
    
    0 讨论(0)
  • 2021-01-18 02:05

    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
    
    0 讨论(0)
提交回复
热议问题