通过在共同的LISP对象的内存使用情况(memory usage by objects in com

2019-06-27 16:34发布

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.

Answer 1:

据我所知,目前还没有这样的标准任意对象,但也有实现相关的解决方案,如ccl:object-direct-size在CCL:

CL-USER> (object-direct-size "foo")
16

但是,要知道,这些是否你想要做什么取决于你所说的“大小”的意思,因为这些功能通常不包括的组件对象引用的大小。 您也可以运行GC,初始化几个对象和比较 room的输出之前和之后。

另外,还要注意time通常包括分配信息:

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

也许你可以尝试这样的事情(未经测试,其实只是一个快速的黑客):

(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))

例如:

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


Answer 2:

在Common Lisp的克洛斯对象通常是时隙的集合。 通常,这些插槽可以被存储在内部的某种载体。 CLOS槽将通常包含一个指针到一些数据对象,或者对于一些基本数据类型,可以包括数据本身。 这些基本数据类型必须适应一个存储器字:实例是fixnums和字符。 常见Lisp实现通常不内嵌更复杂的数据结构转换成一个槽。 例如,一个时隙可被声明为包含fixnums的向量。 实现不会分配CLOS对象内这个矢量。 的CLOS对象将指向矢量对象。

克洛斯对象本身应该占据然后:插槽数*字长+开销。

让我们假设一个字是4个字节,32位。

这可能是有十个插槽克洛斯对象的大小:

10 slots * 4 bytes + 8 bytes = 48 bytes

现在,假设对一个不同的字符串一个CLOS物点的每个时隙和每个串是100个字节长。

从上面的例子:

1 CLOS object + 10 strings each 100 bytes.

48 bytes + 10 * 100 = 1048 bytes

现在想象一下,每个插槽指向同一个字符串:

1 CLOS object + 1 string of 100 bytes.

48 bytes + 100 bytes = 148 bytes

为了计算CLOS对象,您可以任意的大小:

  • 只是算CLOS对象本身的大小。 这很简单。

  • 以某种方式计算的对象的一个​​图表,是从物体到达,确定该唯一的存储器的对象(减去直接分配原始对象),总结那些的所有存储器大小。



Answer 3:

我也有在CL web框架,也用同样的会议问题所困扰,这里是送给我什么宇宙https://people.gnome.org/~xan/memory.lisp似乎在SBCL工作

(memory::dump-memory (weblocks::active-sessions))
Total memory used: 99.785706 MB


文章来源: memory usage by objects in common lisp