Сборка мусора
Когда программа создает список или пользователь определяет новую функцию (например, загружая библиотеку), эти данные размещаются в обычной памяти. Если обычной памяти становится мало, Emacs просит операционную систему выделить дополнительную память. Разные типы объектов Lisp, такие как символы, cons-ячейки, небольшие векторы, маркеры и т. д., размещаются в отдельных блоках памяти. (Большие векторы, длинные строки, буферы и некоторые другие объекты редактирования, размер которых достаточно велик, размещаются в отдельных блоках — по одному на объект; небольшие строки упаковываются в блоки по 8k байт, а небольшие векторы — в блоки по 4k байт).
Помимо обычных векторов, многие объекты, например маркеры, наложения и буферы, управляются так, как если бы они были векторами. Соответствующие структуры данных C содержат поле union vectorlike_header, член size которого содержит подтип, перечисленный в enum pvec_type, а также информацию о том, сколько полей Lisp_Object содержит эта структура и каков размер оставшихся данных. Эта информация нужна для вычисления объема памяти, занимаемого объектом, и используется кодом выделения памяти для векторов при обходе блоков векторов.
Часто некоторое время используют часть памяти, а затем освобождают ее, например уничтожая буфер или удаляя последнюю ссылку на объект. Emacs предоставляет сборщик мусора, который освобождает эту неиспользуемую память. По сути, сборщик мусора находит и помечает все объекты Lisp, к которым программы Lisp по-прежнему могут получить доступ. Для начала он предполагает, что доступны все символы, их значения и связанные с ними определения функций, а также любые данные, находящиеся в данный момент в стеке. Объекты, к которым можно косвенно обратиться через другие доступные объекты, также считаются доступными, однако вычисление выполняется «консервативно», поэтому число доступных объектов может быть немного завышено.
После завершения маркировки все непомеченные объекты считаются мусором. Что бы ни делала программа Lisp или пользователь, обратиться к ним невозможно, поскольку способ добраться до них больше отсутствует. Их память можно использовать повторно, так как никому они не понадобятся. На втором этапе (очистки) сборщик мусора организует повторное использование этой памяти. (Однако поскольку маркировка выполнялась «консервативно», один проход сборщика мусора не гарантирует очистку всех неиспользуемых объектов.)
На этапе очистки неиспользуемые cons-ячейки помещаются в список свободных элементов для последующего выделения памяти; то же происходит с символами и маркерами. Доступные строки уплотняются, чтобы занимать меньше блоков по 8k; затем остальные блоки по 8k освобождаются. Недоступные векторы из блоков векторов объединяются, чтобы создать максимально возможные свободные области; если свободная область занимает целый блок по 4k, этот блок освобождается. В противном случае свободная область записывается в массив списков свободных элементов, где каждая запись соответствует списку свободных областей одинакового размера. Память для больших векторов, буферов и других крупных объектов выделяется и освобождается по отдельности.
Примечание для Common Lisp: В отличие от других реализаций Lisp, GNU Emacs Lisp не запускает сборщик мусора, когда список свободных элементов пуст. Вместо этого он просто запрашивает у операционной системы дополнительную память, и выполнение продолжается, пока не будет использовано
gc-cons-thresholdбайт.Это означает, что можно гарантировать, что сборщик мусора не будет запущен во время определенной части программы Lisp, если вызвать его явно непосредственно перед этой частью (при условии, что она не использует столько памяти, чтобы потребовался еще один запуск сборщика мусора).
- Функция: garbage-collect-heapsize
-
Эта функция возвращает сведения о текущем использовании памяти. Возвращаемое значение — список со сведениями об используемой памяти; каждая запись имеет вид ‘(name size used)’ или ‘(name size used free)’. В записи name — символ, обозначающий тип объектов, к которым относится эта запись, size — число байт, занимаемых каждым объектом, used — число этих объектов, найденных в куче и остающихся в использовании, а необязательное значение free — число таких объектов, которые не используются, но сохраняются Emacs для будущих выделений памяти. Общий результат выглядит так:
((
consescons-size used-conses free-conses) (symbolssymbol-size used-symbols free-symbols) (stringsstring-size used-strings free-strings) (string-bytesbyte-size used-bytes) (vectorsvector-size used-vectors) (vector-slotsslot-size used-slots free-slots) (floatsfloat-size used-floats free-floats) (intervalsinterval-size used-intervals free-intervals) (buffersbuffer-size used-buffers) (heapunit-size total-size free-size))Пример:
(garbage-collect) ⇒ ((conses 16 49126 8058) (symbols 48 14607 0) (strings 32 2942 2607) (string-bytes 1 78607) (vectors 16 7247) (vector-slots 8 341609 29474) (floats 8 71 102) (intervals 56 27 26) (buffers 944 8) (heap 1024 11715 2678))Ниже приведена таблица с описанием каждого элемента. Обратите внимание, что последняя запись
heapявляется необязательной и присутствует только в том случае, если базовая реализацияmallocпредоставляет функциюmallinfo.- cons-size
-
Внутренний размер cons-ячейки, то есть
sizeof (struct Lisp_Cons). - used-conses
-
Количество используемых cons-ячеек.
- free-conses
-
Количество cons-ячеек, память для которых получена от операционной системы, но которые в данный момент не используются.
- symbol-size
-
Внутренний размер символа, то есть
sizeof (struct Lisp_Symbol). - used-symbols
-
Количество используемых символов.
- free-symbols
-
Количество символов, память для которых получена от операционной системы, но которые в данный момент не используются.
- string-size
-
Внутренний размер заголовка строки, то есть
sizeof (struct Lisp_String). - used-strings
-
Количество используемых заголовков строк.
- free-strings
-
Количество заголовков строк, память для которых получена от операционной системы, но которые в данный момент не используются.
- byte-size
-
Этот элемент используется для удобства и равен
sizeof (char). - used-bytes
-
Общий размер данных всех строк в байтах.
- vector-size
-
Размер в байтах вектора длины 1, включая его заголовок.
- used-vectors
-
Количество заголовков векторов, выделенных из блоков векторов.
- slot-size
-
Внутренний размер слота вектора, всегда равный
sizeof (Lisp_Object). - used-slots
-
Количество слотов во всех используемых векторах. В зависимости от платформы в число слотов могут входить некоторые или все накладные расходы, связанные с заголовками векторов.
- free-slots
-
Количество свободных слотов во всех блоках векторов.
- float-size
-
Внутренний размер объекта с плавающей точкой, то есть
sizeof (struct Lisp_Float). (Не путайте его сfloatилиdoubleнативной платформы.) - used-floats
-
Количество используемых объектов с плавающей точкой.
- free-floats
-
Количество объектов с плавающей точкой, память для которых получена от операционной системы, но которые в данный момент не используются.
- interval-size
-
Внутренний размер объекта-интервала, то есть
sizeof (struct interval). - used-intervals
-
Количество используемых интервалов.
- free-intervals
-
Количество интервалов, память для которых получена от операционной системы, но которые в данный момент не используются.
- buffer-size
-
Внутренний размер буфера, то есть
sizeof (struct buffer). (Не путайте его со значением, возвращаемым функциейbuffer-size.) - used-buffers
-
Количество используемых объектов-буферов. Сюда входят уничтоженные буферы, невидимые для пользователей, то есть все буферы в списке
all_buffers. - unit-size
-
Единица измерения объема кучи, всегда равная 1024 байтам.
- total-size
-
Общий размер кучи в единицах unit-size.
- free-size
Неиспользуемая в данный момент память кучи в единицах unit-size.
- Команда: garbage-collect
-
Эта команда запускает сборку мусора и возвращает сведения об объеме используемой памяти. (Сборка мусора также может произойти автоматически, если с момента предыдущей сборки мусора вы используете более
gc-cons-thresholdбайт данных Lisp.)garbage-collectвозвращает тот же список, что и показанный выше дляgarbage-collect-heapsize.
- Пользовательский параметр: garbage-collection-messages
Если значение этой переменной не равно
nil, Emacs выводит сообщение в начале и в конце сборки мусора. Значение по умолчанию —nil.
- Переменная: post-gc-hook
Это обычный хук, который запускается по завершении сборки мусора. Во время выполнения функций хука сборка мусора приостанавливается, поэтому будьте осторожны при их написании.
- Пользовательский параметр: gc-cons-threshold
-
Значение этой переменной задает число байт памяти, которое должно быть выделено для объектов Lisp после одной сборки мусора, чтобы запустить следующую сборку мусора. Результат, возвращаемый
garbage-collect, позволяет получить сведения о размере объектов определенного типа; память, выделенная для содержимого буферов, не учитывается.Начальное значение порога —
GC_DEFAULT_THRESHOLD, оно определено в alloc.c. Поскольку оно задано в единицахword_size, для стандартной 32-разрядной конфигурации его значение равно 400,000, а для 64-разрядной и для 32-разрядных сборок, настроенных с параметром --with-wide-int, — 800,000. Если указать большее значение, сборка мусора будет происходить реже. Это уменьшает время, затрачиваемое на сборку мусора (поэтому программы Lisp будут работать быстрее между более редкими циклами сборки мусора), но увеличивает общее использование памяти. Это может быть полезно при запуске программы, создающей много данных Lisp, особенно если требуется ускорить ее работу. Однако мы не рекомендуем надолго увеличивать порог и советуем никогда не устанавливать его выше значения, необходимого для работы программы с приемлемой скоростью. Использование порогов выше необходимого может усилить общесистемную нагрузку на память, а также значительно увеличить длительность каждого цикла сборки мусора, поэтому этого следует избегать.Чтобы сборка мусора происходила чаще, укажите меньшее значение, вплоть до 1/10 от
GC_DEFAULT_THRESHOLD. Значение меньше этого минимума будет действовать только до следующей сборки мусора; после нееgarbage-collectвернет порог к минимальному значению.
- Пользовательский параметр: gc-cons-percentage
-
Значение этой переменной задает объем выделения памяти перед началом сборки мусора как долю от текущего размера кучи. Этот критерий и
gc-cons-thresholdдействуют параллельно, и сборка мусора происходит только при выполнении обоих условий.По мере увеличения размера кучи время выполнения сборки мусора возрастает. Поэтому может быть целесообразно проводить ее реже пропорционально этому увеличению.
Начальное значение процента равно 0.1 в интерактивных сеансах и при создании дампа Emacs (см. Сборка Emacs) и 1.0 в неинтерактивных сеансах (так называемых пакетных сеансах).
Как и в случае с
gc-cons-threshold, не увеличивайте это значение больше необходимого и никогда не оставляйте его повышенным надолго.
Управление сборщиком мусора с помощью gc-cons-threshold и gc-cons-percentage является лишь приблизительным. Хотя Emacs регулярно проверяет, не превышен ли порог, из соображений эффективности он не делает этого немедленно после каждого изменения кучи или gc-cons-threshold либо gc-cons-percentage, поэтому превышение порога не запускает сборку мусора сразу. Кроме того, для эффективного расчета порога Emacs приблизительно оценивает размер кучи, то есть число байт, используемых доступными в данный момент объектами в куче.
Значение, возвращаемое garbage-collect, описывает объем памяти, используемой данными Lisp, с разбивкой по типам данных. В отличие от нее, функция memory-limit предоставляет сведения об общем объеме памяти, используемой Emacs в данный момент.
- Функция: memory-limit
Эта функция возвращает оценку общего объема виртуальной памяти в байтах, используемой Emacs в данный момент, деленную на 1024. С ее помощью можно получить общее представление о том, как ваши действия влияют на использование памяти.
- Переменная: memory-full
Значение этой переменной равно
t, если в Emacs почти закончилась память для объектов Lisp, иnilв противном случае.
- Функция: memory-use-counts
Функция возвращает список чисел, подсчитывающих количество объектов, созданных в текущем сеансе Emacs. Каждый счетчик увеличивается для определенного типа объектов. Подробности см. в строке документации.
- Функция: memory-info
-
Эта функция возвращает общий объем системной памяти и объем свободной памяти. В неподдерживаемой системе значением может быть
nil.Если
default-directoryуказывает на удаленный узел, возвращаются сведения о памяти этого узла.
- Переменная: gcs-done
Эта переменная содержит общее количество сборок мусора, выполненных на данный момент в текущем сеансе Emacs.
- Переменная: gc-elapsed
Эта переменная содержит общее количество секунд, затраченных на сборку мусора в текущем сеансе Emacs, в виде числа с плавающей точкой.
- Функция: memory-report
-
Иногда бывает полезно посмотреть, на что Emacs расходует память (в различных переменных, буферах и кэшах). Эта команда откроет новый буфер (под названием ‘"*Memory Report*"’) с общими сведениями, а также списком «самых больших» буферов и переменных.
Все приведенные здесь данные приблизительны, поскольку не существует единого способа вычислить размер переменной. Например, две переменные могут совместно использовать части структуры данных, и в этом случае они будут учтены дважды. Тем не менее эта команда может дать полезное общее представление о том, какие части Emacs расходуют память.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Garbage-Collection.html