Модуль Gc
module Gc: sig .. end
Управление памятью и статистика; финализируемые значения.
type stat = {
minor_words :
| (* |
Количество слов, выделенных в младшей куче с момента запуска программы. |
*) | |
promoted_words :
| (* |
Количество слов, выделенных в младшей куче, переживших сборку младшей кучи и перемещённых в старшую кучу с момента запуска программы. |
*) | |
major_words :
| (* |
Количество слов, выделенных в старшей куче, включая перемещённые слова, с момента запуска программы. |
*) | |
minor_collections :
| (* |
Количество сборок младшей кучи с момента запуска программы. |
*) | |
major_collections :
| (* |
Количество завершённых циклов сборки старшей кучи с момента запуска программы. |
*) | |
heap_words :
| (* |
Общий размер старшей кучи в словах. |
*) | |
heap_chunks :
| (* |
Количество непрерывных участков памяти, из которых состоит старшая куча. В настоящее время эта метрика недоступна в OCaml 5: значение поля всегда равно |
*) | |
live_words :
| (* |
Количество слов с живыми данными в старшей куче, включая слова заголовков. Обратите внимание: «живыми» считаются все слова в старшей куче, которые на данный момент не признаны подлежащими сборке; сюда входят слова, ставшие недостижимыми для программы после начала предыдущего цикла GC. Обычно гораздо проще и предсказуемее вызвать |
*) | |
live_blocks :
| (* |
Количество живых блоков в старшей куче. Оговорку относительно значения термина «живой» см. в |
*) | |
free_words :
| (* |
Количество слов в списке свободных блоков. |
*) | |
free_blocks :
| (* |
Количество блоков в списке свободных блоков. В настоящее время эта метрика недоступна в OCaml 5: значение поля всегда равно |
*) | |
largest_free :
| (* |
Размер (в словах) самого большого блока в списке свободных блоков. В настоящее время эта метрика недоступна в OCaml 5: значение поля всегда равно |
*) | |
fragments :
| (* |
Количество потерянных из-за фрагментации слов. Это свободные блоки размером в одно слово, расположенные между двумя живыми блоками. Они недоступны для выделения памяти. |
*) | |
compactions :
| (* |
Количество уплотнений кучи с момента запуска программы. |
*) | |
top_heap_words :
| (* |
Максимальный размер старшей кучи в словах. |
*) | |
stack_size :
| (* |
Текущий размер текущего стека OCaml в словах.
|
*) | |
forced_major_collections :
| (* |
Количество принудительно выполненных полных сборок старшей кучи с момента запуска программы.
|
*) | |
live_stacks_words :
| (* |
Общий объём памяти, выделенной вне кучи OCaml для фрагментов стека. Сюда входят метаданные стека и фрагменты стека, хранящиеся в кэше фрагментов стека.
|
*) |
} Счётчики управления памятью возвращаются в виде записи stat. Эти счётчики содержат значения для всей программы.
Общий объём памяти, выделенной программой с момента запуска, равен (в словах) minor_words + major_words - promoted_words. Умножьте это значение на размер слова (4 для 32-разрядной машины, 8 для 64-разрядной), чтобы получить количество байтов.
type control = {
minor_heap_size :
| (* |
Размер младшей кучи (в словах). Изменение этого параметра запускает сборку младшей кучи. Общий размер младшей кучи, используемой этой программой, равен сумме размеров куч активных доменов. Значение по умолчанию: 256k. |
*) | |
major_heap_increment :
| (* |
На сколько увеличивать старшую кучу при её расширении. Если это число меньше или равно 1000, оно задаётся в процентах от текущего размера кучи (например, значение 100 удваивает размер кучи при каждом расширении). Если число больше 1000, оно задаёт фиксированное количество слов, добавляемых к куче. В настоящее время это поле недоступно в OCaml 5: его значение всегда равно |
*) | |
space_overhead :
| (* |
Скорость работы сборщика мусора старшей кучи вычисляется на основе этого параметра и
|
*) | |
verbose :
| (* |
Это значение управляет сообщениями GC, выводимыми в стандартный поток ошибок. Оно является суммой некоторых из следующих флагов, включающих вывод сообщений при соответствующих событиях:
|
*) | |
max_overhead :
| (* |
Уплотнение кучи запускается, когда расчётный объём «потерянной» памяти превышает В настоящее время это поле недоступно в OCaml 5: его значение всегда равно |
*) | |
stack_limit :
| (* |
Максимальный размер стеков волокон (в словах). Значение по умолчанию: 128M. |
*) | |
allocation_policy :
| (* |
Политика выделения памяти в старшей куче. В настоящее время это поле недоступно в OCaml 5: его значение всегда равно До OCaml 5.0 допустимыми значениями были 0, 1 и 2.
|
*) | |
window_size :
| (* |
Размер окна, используемого GC старшей кучи для сглаживания колебаний рабочей нагрузки. Целое число от 1 до 50.
|
*) | |
custom_major_ratio :
| (* |
Целевое отношение объёма неосвобождённой памяти к размеру старшей кучи для памяти вне кучи, занятой пользовательскими значениями, размещёнными в старшей куче. Скорость GC корректируется так, чтобы для ещё не собранных мёртвых значений использовался примерно такой объём памяти. Значение задаётся в процентах от размера старшей кучи. Значение по умолчанию поддерживает объём неосвобождённой внешней памяти примерно равным дополнительному объёму памяти внутри кучи. Примечание: это относится только к значениям, выделенным с помощью
|
*) | |
custom_minor_ratio :
| (* |
Ограничение на объём неосвобождённой памяти вне кучи, занятой пользовательскими значениями в младшей куче. Сборка младшей кучи запускается, когда пользовательские значения, расположенные в младшей куче, занимают такой объём памяти. Значение задаётся в процентах от размера младшей кучи. Примечание: это относится только к значениям, выделенным с помощью
|
*) | |
custom_minor_max_size :
| (* |
Максимальный объём памяти вне кучи для каждого пользовательского значения, выделенного в младшей куче. Пользовательские значения, занимающие больше этого количества байтов, выделяются в старшей куче. Примечание: это относится только к значениям, выделенным с помощью
|
*) |
} Параметры GC задаются в виде записи control. Обратите внимание, что эти параметры также можно инициализировать, задав переменную окружения OCAMLRUNPARAM. См. документацию к ocamlrun.
val stat : unit -> stat
Возвращает текущие значения счётчиков управления памятью в записи stat, содержащей общую статистику памяти программы. Метрики heap_chunks, free_blocks, largest_free и stack_size в настоящее время недоступны в OCaml 5, поэтому значения соответствующих возвращаемых полей равны 0. Эта функция выполняет полную сборку старшей кучи.
val quick_stat : unit -> stat
Возвращает запись с текущими значениями счётчиков управления памятью, например stat. В отличие от stat, функция quick_stat не выполняет полную сборку старшей кучи и поэтому работает намного быстрее. Однако quick_stat возвращает значения счётчиков, полученные при последней сборке младшей кучи или в конце последнего цикла сборки старшей кучи (в зависимости от того, что произошло позже). Поэтому статистика памяти, возвращаемая quick_stat, не является мгновенно точной.
val counters : unit -> float * float * float
Возвращает (minor_words, promoted_words, major_words) для текущего домена или, возможно, предыдущих доменов. Эта функция работает так же быстро, как quick_stat.
val minor_words : unit -> float
Количество слов, выделенных в младшей куче этим доменом или, возможно, предыдущими доменами. Это значение точно для программ с байт-кодом, но является лишь приблизительным для программ, скомпилированных в машинный код.
В машинном коде эта функция не выделяет память.
- Начиная с версии 4.04
val get : unit -> control
Возвращает текущие значения параметров GC в записи control.
Поля major_heap_increment, max_overhead, allocation_policy и window_size в настоящее время недоступны в OCaml 5, поэтому значения соответствующих возвращаемых полей равны 0.
- Предупреждение unsynchronized_access. Параметры GC являются изменяемым глобальным состоянием.
val set : control -> unit
set r изменяет параметры GC в соответствии с записью control r. Обычный способ использования: Gc.set { (Gc.get()) with Gc.verbose = 0x00d }
Поля major_heap_increment, max_overhead, allocation_policy и window_size в настоящее время недоступны в OCaml 5, поэтому их изменение не оказывает никакого эффекта.
- Предупреждение unsynchronized_access. Параметры GC являются изменяемым глобальным состоянием.
val minor : unit -> unit
Запускает сборку младшей кучи.
val major_slice : int -> int
major_slice n Выполняет сборку младшей кучи и один фрагмент сборки старшей кучи. n — размер фрагмента: GC выполнит достаточно работы, чтобы в среднем освободить n слов памяти. Если n = 0, GC постарается выполнить достаточно работы, чтобы следующий автоматический фрагмент не требовал работы. Эта функция возвращает неопределённое целое число (в настоящее время: 0).
val major : unit -> unit
Выполняет сборку младшей кучи и завершает текущий цикл сборки старшей кучи.
val full_major : unit -> unit
Выполняет сборку младшей кучи, завершает текущий цикл сборки старшей кучи и запускает полный новый цикл. В результате будут собраны все блоки, которые в данный момент недостижимы.
val compact : unit -> unit
Выполняет полную сборку старшей кучи и уплотняет кучу. Обратите внимание, что уплотнение кучи — длительная операция.
val print_stat : out_channel -> unit
Выводит в канал, переданный в качестве аргумента, текущие значения счётчиков управления памятью всей программы в удобочитаемом виде.
val allocated_bytes : unit -> float
Возвращает количество байтов, выделенных этим доменом и, возможно, предыдущим доменом. Значение возвращается в виде float, чтобы избежать переполнения при использовании int на 32-разрядных машинах.
val get_minor_free : unit -> int
Возвращает текущий размер свободного пространства внутри младшей кучи этого домена.
- Начиная с версии 4.03
val finalise : ('a -> unit) -> 'a -> unit
finalise f v регистрирует f как функцию финализации для v. v должен быть выделен в куче. f будет вызвана с аргументом v в некоторый момент между тем, когда v впервые станет недостижимым (в том числе через слабые указатели), и тем, когда v будет собран GC. Для одного значения можно зарегистрировать несколько функций, в том числе несколько экземпляров одной и той же функции. Каждый экземпляр будет вызван один раз (или не будет вызван, если программа завершится до того, как v станет недостижимым).
GC вызывает функции финализации в порядке освобождения памяти. Если несколько значений становятся недостижимыми одновременно (то есть в течение одного цикла GC), функции финализации вызываются в обратном порядке соответствующих вызовов finalise. Если finalise вызывается в том же порядке, в котором выделяются значения, каждое значение финализируется до значений, от которых оно зависит. Разумеется, это перестаёт быть верным, если присваивания добавляют новые зависимости.
При наличии нескольких потоков OCaml следует считать, что любой конкретный финализатор может выполняться в любом из потоков.
Всё, что достижимо из замыкания функций финализации, считается достижимым, поэтому следующий код не будет работать ожидаемым образом:
let v = ... in Gc.finalise (fun _ -> ...v...) v
Вместо этого следует убедиться, что v не входит в замыкание функции финализации, написав следующий код:
let f = fun x -> ... let v = ... in Gc.finalise f v
Функция f может использовать все возможности OCaml, включая присваивания, которые снова делают значение достижимым. Она также может зациклиться навсегда (в этом случае другие функции финализации не будут вызваны во время выполнения f, если только она не вызовет finalise_release). Она может вызвать finalise для v или других значений, чтобы зарегистрировать другие функции или даже саму себя. Она может вызвать исключение; в этом случае исключение прервёт действие, которое выполняла программа в момент вызова функции.
finalise вызовет Invalid_argument, если для v не гарантировано размещение в куче. Примеры значений, которые не размещаются в куче: целые числа, конструкторы-константы, логические значения, пустой массив, пустой список и значение типа unit. Точный перечень значений, размещаемых в куче и не размещаемых в ней, зависит от реализации. Некоторые константные значения могут размещаться в куче, но не освобождаться в течение времени жизни программы; например, список целочисленных констант. Это также зависит от реализации. Обратите внимание, что значения типов float иногда размещаются в куче, а иногда нет, поэтому их финализация небезопасна, и finalise также вызовет Invalid_argument для таких значений. Значения типа 'a Lazy.t (для любого 'a) в этом отношении аналогичны float, за исключением того, что компилятор иногда оптимизирует их так, что finalise не может их обнаружить. В этом случае исключение Invalid_argument вызвано не будет, однако всё равно следует избегать вызова finalise для отложенных значений.
Результаты вызовов String.make, Bytes.make, Bytes.create, Array.make и ref гарантированно размещаются в куче и не являются константами, если только аргумент длины не равен 0.
val finalise_last : (unit -> unit) -> 'a -> unit
аналогично Gc.finalise, за исключением того, что значение не передаётся в качестве аргумента. Поэтому указанное значение нельзя использовать для вычисления функции финализации. Преимущество в том, что функция вызывается после того, как значение в последний раз стало недостижимым, а не в первый раз. Поэтому, в отличие от Gc.finalise, значение больше никогда не станет достижимым и не будет использовано. В частности, перед выполнением функции финализации сбрасываются все слабые указатели и эпhemeron, содержащие это значение в качестве ключа или данных. Кроме того, функции финализации, добавленные с помощью Gc.finalise, всегда вызываются до функций финализации, добавленных с помощью Gc.finalise_last.
- Начиная с версии 4.04
val finalise_release : unit -> unit
Функция финализации может вызвать finalise_release, чтобы сообщить GC, что следующую функцию финализации можно запустить, не дожидаясь завершения текущей.
type alarm
Сигнализация — это объект, вызывающий пользовательскую функцию в конце цикла сборки старшей кучи. Для создания и удаления сигнализаций предусмотрены следующие функции.
val create_alarm : (unit -> unit) -> alarm
create_alarm f обеспечит вызов f в конце циклов полной сборки мусора, не вызванных самим f, начиная с текущего или следующего цикла. f будет выполняться в том же домене, который создал сигнал, пока домен не завершит работу или не будет вызвано delete_alarm. Возвращается значение типа alarm, которое можно использовать для вызова delete_alarm.
Не гарантируется, что сигнал Gc будет срабатывать в конце каждого цикла полной сборки мусора, но гарантируется, что он сработает в конечном итоге.
Например, вот простой способ прервать функцию, если потребление памяти программой превысит заданный limit в МБ; этот способ подходит для использования в toplevel:
let run_with_memory_limit (limit : int) (f : unit -> 'a) : 'a =
let limit_memory () =
let mem = Gc.(quick_stat ()).heap_words in
if mem / (1024 * 1024) > limit / (Sys.word_size / 8) then
raise Out_of_memory
in
let alarm = Gc.create_alarm limit_memory in
Fun.protect f ~finally:(fun () -> Gc.delete_alarm alarm ; Gc.compact ())
val delete_alarm : alarm -> unit
delete_alarm a прекратит вызовы функции, связанной с a. Повторный вызов delete_alarm a не даст никакого эффекта.
val eventlog_pause : unit -> unit
val eventlog_resume : unit -> unit
module Memprof: sig .. end
Memprof — это механизм профилирования, который случайным образом выбирает слова выделенной памяти.
type suspended_collection_work
val ramp_up : (unit -> 'a) -> 'a * suspended_collection_work
В общем случае сборщик мусора OCaml предполагает, что программа работает в «стационарном состоянии», при котором пиковое потребление памяти остается постоянным: для каждого нового выделенного слова он предполагает, что одно слово стало недостижимым, и пытается собрать его во время следующего этапа сборки мусора.
Это предположение неверно в те моменты выполнения программы, когда объем используемой памяти растет, а не остается стабильным: предположение о стационарном состоянии заставляет сборщик мусора работать интенсивнее без какой-либо пользы, поскольку он не сможет собрать больше памяти.
ramp_up f переводит текущий домен в фазу «наращивания» на время вычисления f (), сообщая сборщику мусора, что предположение о стационарном состоянии неверно; этот механизм следует использовать, когда известно, что объем используемой программой памяти значительно увеличится.
Во время фазы наращивания сборщик мусора не будет увеличивать объем работы для новых выделений памяти: соответствующая работа по сборке мусора «приостанавливается». Общее количество приостановленной работы по сборке мусора возвращается ramp_up вместе с результатом функции.
Если пользователь отбросит эту приостановленную работу (не предпринимая никаких действий), сборщик мусора никогда не ускорится, чтобы освободить соответствующий объем памяти. Это подходит, если работа по наращиванию выделяет долгоживущую память, которая остается используемой до конца выполнения программы.
Если пользователь знает, что в определенный момент выполнения программы объем используемой памяти уменьшился на соответствующую величину — как правило, потому что память, выделенная во время ramp_up, больше не используется, — следует вызвать Gc.ramp_down ниже, чтобы сборщик мусора «возобновил» эту работу по сборке мусора.
Если f () вызывает исключение, фаза наращивания завершается, приостановленная работа по сборке мусора возобновляется, а исключение вызывается повторно.
Если f () выполняет эффект, этот эффект не обрабатывается, и вместо этого выбрасывается исключение Effect.Unhandled.
val ramp_down : suspended_collection_work -> unit
Уведомляет сборщик мусора о некотором объеме работы по сборке мусора, приостановленной во время фазы наращивания, чтобы возобновить ее сейчас.
module Tweak: sig .. end
Настройки GC — это нестабильные и недокументированные параметры сборщика мусора, доступные для конфигурирования и предназначенные главным образом для разработчиков сборщика мусора.
© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/api/Gc.html