использование памяти объектами в common lisp

есть ли способ узнать, сколько памяти используется экземпляром класса или основных типов данных в целом?

У меня есть игрушка webframework в cl, которая создает и управляет веб-страницами с экземплярами классов, которые представляют теги html и их свойства, и поскольку они должны сделать html-страницу, у них есть дети в слоте под названием Дети. поэтому я думал, сколько сеанс пользователя будет стоить серверу, если я возьму этот подход. Спасибо.

3 ответов


насколько я знаю, в стандарте нет ничего подобного для произвольных объектов, но есть решения, зависящие от реализации, такие как 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

в Common Lisp объекты CLOS обычно представляют собой набор слотов. Как правило, эти слоты Могут быть внутренне сохранены в каком-то векторе. Слоты CLOS обычно содержат указатель на какой-либо объект данных или, для нескольких примитивных типов данных, могут включать сами данные. Эти примитивные типы данных должны вписываться в слово памяти: примерами являются fixnums и символы. Общие реализации Lisp обычно не вставляют более сложные структуры данных в слот. Например, слот может будет объявлено, что содержит вектор fixnums. Реализации не будут выделять этот вектор внутри объекта CLOS. Объект CLOS будет указывать на векторный объект.

сам объект CLOS должен занимать тогда: количество слотов * размер слова + накладные расходы.

предположим, что слово имеет длину 4 байта, 32 бит.

это может быть размер для объекта CLOS с десятью слотами:

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. Это просто.

  • как-то вычислить график объектов с достижимыми от объекта, определить уникальные объекты памяти (минус прямые выделенные примитивные объекты) и суммировать все размеры памяти.


У меня также есть веб-фреймворк в cl, также боролся с той же проблемой сеансов, и вот что Вселенная отправила мне https://people.gnome.org / ~xan / память.шепелявит Кажется, он работает в sbcl

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