Сбор мусора
Когда программа создаёт список или пользователь определяет новую функцию (например, загружая библиотеку), эти данные помещаются в обычное хранилище. Если обычное хранилище заполняется, Emacs просит операционную систему выделить больше памяти. Различные типы объектов Lisp, такие как символы, ячейки cons, малые векторы, маркеры и т. д., изолированы в отдельных блоках памяти. (Большие векторы, длинные строки, буферы и некоторые другие типы редактирования, которые довольно большие, выделяются в отдельных блоках, по одному на объект; малые строки упакованы в блоки по 8 кБ, а малые векторы — в блоки по 4 кБ).
Помимо базовых векторов, многие объекты, такие как маркеры, наложения и буферы, управляются так, как будто они являются векторами. Соответствующие структуры данных C включают поле union vectorlike_header, чьё член size содержит тип, перечисленный в enum pvec_type, и информацию о количестве полей Lisp_Object в этой структуре и о размере оставшихся данных. Эта информация необходима для расчёта занимаемой объектом памяти и используется кодом выделения векторов при итерации по блокам векторов.
Довольно часто какая-то память используется некоторое время, а затем освобождается (например, при уничтожении буфера или удалении последней ссылки на объект). Emacs предоставляет сборщик мусора для возврата этой оставленной памяти. Сборщик мусора работает, по сути, находя и помечая все объекты Lisp, которые всё ещё доступны программам Lisp. Для начала он предполагает, что все символы, их значения и связанные определения функций, а также все данные в настоящее время в стеке, доступны. Любые объекты, которые могут быть косвенно достигнуты через другие доступные объекты, также доступны, но этот расчёт выполняется «осторожно», поэтому он может немного переоценивать количество доступных объектов.
После завершения помечания все непомеченные объекты являются мусором. Независимо от того, что делает программа Lisp или пользователь, невозможно обратиться к ним, так как больше нет способов их достичь. Их память можно переиспользовать, так как никто не будет по ним скучать. Вторая (очистка) фаза сборщика мусора организует переиспользование памяти. (Но поскольку помечание выполнялось «осторожно», не гарантируется, что все неиспользуемые объекты будут собраны мусором в каждом цикле очистки).
Фаза очистки помещает неиспользуемые ячейки cons в список свободных для последующего выделения; также для символов и маркеров. Она сжимает доступные строки, чтобы они занимали меньше блоков по 8 кБ; затем освобождает другие блоки по 8 кБ. Недоступные векторы из блоков векторов объединяются для создания максимально возможных свободных областей; если свободная область охватывает целый блок по 4 кБ, этот блок освобождается. В противном случае свободная область записывается в массив свободных списков, где каждый элемент соответствует списку свободных областей того же размера. Большие векторы, буферы и другие большие объекты выделяются и освобождаются по отдельности.
Примечание по Common Lisp: В отличие от других Lisp, GNU Emacs Lisp не вызывает сборщик мусора, когда список свободных элементов пуст. Вместо этого он просто запрашивает у операционной системы выделение большего объёма памяти, и обработка продолжается до
gc-cons-thresholdбайт, которые были использованы.Это означает, что вы можете убедиться, что сборщик мусора не будет запущен в течение определённого участка программы Lisp, вызвав сборщик мусора явно незадолго до него (при условии, что эта часть программы не использует столько места, чтобы вызвать повторный сбор мусора).
- Команда: garbage-collect
-
Эта команда запускает сбор мусора и возвращает информацию об используемом объёме памяти. (Сбор мусора также может произойти спонтанно, если вы используете более
gc-cons-thresholdбайтов данных Lisp с момента последнего сбора мусора.)garbage-collectвозвращает список с информацией об используемом объёме памяти, где каждый элемент имеет вид ‘(имя размер использовано)’ или ‘(имя размер использовано свободно)’. В элементе имя — символ, описывающий тип объектов, который он представляет, размер — число байт, используемых каждым, использовано — число таких объектов, которые были обнаружены активными в куче, а необязательное свободно — число таких объектов, которые не активны, но 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.
Если произошёл переполнение в чистой памяти (см. Чистое хранилище), и Emacs был выгружен с помощью метода (теперь устаревшего)
unexec(см. Сборка Emacs), тоgarbage-collectвозвращаетnil, потому что в этом случае настоящий сбор мусора выполнить нельзя.
- Пользовательский параметр: garbage-collection-messages
Если эта переменная не
nil, Emacs отображает сообщение в начале и конце сбора мусора. Значение по умолчанию —nil.
- Переменная: post-gc-hook
Это обычный хук, который выполняется в конце сбора мусора. Сбор мусора запрещён во время работы функций хука, поэтому будьте внимательны при их написании.
- Пользовательский параметр: gc-cons-threshold
-
Значение этой переменной — количество байт памяти, которые должны быть выделены для объектов Lisp после одного сбора мусора, чтобы вызвать другой сбор мусора. Вы можете использовать результат, возвращаемый
garbage-collect, чтобы получить информацию о размере определённого типа объектов; память, выделенная для содержимого буферов, не учитывается.Начальное значение порога —
GC_DEFAULT_THRESHOLD, определённое в alloc.c. Поскольку оно определено в единицахword_size, значение равно 400 000 для 32-битной конфигурации по умолчанию и 800 000 для 64-битной. Если вы укажете большее значение, сбор мусора будет происходить реже. Это уменьшает время, затрачиваемое на сбор мусора, но увеличивает общее использование памяти. Вы можете сделать это, когда запускаете программу, которая создаёт много данных Lisp.Вы можете сделать сборы более частыми, указав меньшее значение, до 1/10 от
GC_DEFAULT_THRESHOLD. Значение меньше этого минимума останется в силе только до следующего сбора мусора, после чегоgarbage-collectвернёт порог к минимуму.
- Пользовательский параметр: gc-cons-percentage
-
Значение этой переменной указывает объём выделения cons перед запуском сбора мусора как часть текущего размера кучи. Это условие и
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.
- Переменная: gcs-done
Эта переменная содержит общее количество сборок мусора, проведённых до сих пор в этом сеансе Emacs.
- Переменная: gc-elapsed
Эта переменная содержит общее количество секунд затраченного времени во время сборок мусора до сих пор в этом сеансе Emacs, как число с плавающей точкой.
- Функция: memory-report
-
Иногда полезно увидеть, где Emacs использует память (в различных переменных, буферах и кэшах). Эта команда откроет новый буфер (называемый «"*Отчёт о памяти*"»), который предоставит общий обзор, в дополнение к списку «самых больших» буферов и переменных.
Все данные здесь приблизительные, потому что нет действительно последовательного способа вычисления размера переменной. Например, две переменные могут совместно использовать части структуры данных, и это будет учтено дважды, но эта команда всё ещё может дать полезный общий обзор тех частей Emacs, которые используют память.
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Garbage-Collection.html