В этом разделе описаны кодировки событий, записываемых в журнал событий GHC. Эти события могут содержать сведения о планировании потоков, статистику сборки мусора, информацию профилирования и пользовательские трассировочные события.
Этот раздел предназначен для разработчиков инструментов, обрабатывающих эти события. В состав GHC входит заголовочный файл C (EventlogFormat.h), содержащий символьные имена идентификаторов типов событий, описанных в этом файле.
17.1. Формат журнала событий
Формат разработан с учётом возможности расширения: старые инструменты должны уметь разбирать (хотя и не обязательно понимать все части) новые версии формата, а новые инструменты — старые файлы журналов.
Формат не зависит от порядка байтов: все значения представлены в порядке от старшего байта к младшему.
Формат допускает расширение:
Заголовок содержит описание каждого типа события и его длины. Инструменты, не распознающие определённый тип события, могут пропустить такие события.
В спецификации типа события предусмотрено место для дополнительной информации, которую старые инструменты могут игнорировать.
К событиям можно добавлять дополнительную информацию, но существующие поля изменять нельзя. Инструменты должны игнорировать дополнительные поля в конце записи события.
Поток журнала событий начинается с заголовка, описывающего типы событий (EventType), присутствующие в файле. За заголовком следуют сами записи событий (Event), каждая из которых начинается с идентификатора типа события и 64-битной временной метки:
EventLog :
EVENT_HEADER_BEGIN
EVENT_HET_BEGIN -- header event types begin
EventType*
EVENT_HET_END -- header event types end
EVENT_HEADER_END
EVENT_DATA_BEGIN
Event*
EVENT_DATA_END
EventType :
EVENT_ET_BEGIN
Word16 -- event type id, unique identifier for this event
Int16 -- >=0 size of the event record in bytes (minus the event type id and timestamp fields)
-- -1 variable size
Word32 -- size of the event description in bytes
Word8* -- event description, UTF8 encoded string describing the event
Word32 -- size of the extra info in bytes
Word8* -- extra info (for future extensions)
EVENT_ET_END
Event :
Word16 -- event type id, as included in the event log header
Word64 -- timestamp (nanoseconds)
[Word16] -- length of the rest (optional, for variable-sized events only)
... event specific info ...
Существует два класса типов событий:
Фиксированного размера: все записи событий фиксированного типа имеют одинаковую длину, указанную в заголовке журнала событий.
Переменного размера: каждая запись события содержит поле длины.
17.2. Диагностика системы времени выполнения
В приведённой ниже документации используются следующие типы данных
ThreadId ~ Word32
CapNo ~ Word16
CapSetId ~ Word32
17.2.1. Наборы капабилити
Эти события описывают наборы капабилити, которые характеризуют структуру выполняемой программы.
В настоящее время определены следующие наборы капабилити:
CAPSET_TYPE_CUSTOM == 1: зарезервирован для приложений конечных пользователей
CAPSET_TYPE_OSPROCESS == 2: капабилити, принадлежащие одному процессу ОС
CAPSET_TYPE_CLOCKDOMAIN == 3: капабилити, использующие одни и те же локальные часы
CAPSET_CREATE
Тег:
25
Длина:
фиксированная
Поле CapSetId:
Набор капабилити
Поле CapSetType:
Тип набора капабилити
Создание набора капабилити.
CAPSET_DELETE
Тег:
26
Длина:
фиксированная
Поле CapSetId:
Набор капабилити
Удаление набора капабилити.
CAPSET_ASSIGN_CAP
Тег:
27
Длина:
фиксированная
Поле CapSetId:
Набор капабилити
Поле CapNo:
Добавляемая капабилити.
Добавление капабилити в набор.
CAPSET_REMOVE_CAP
Тег:
28
Длина:
фиксированная
Поле CapSetId:
Набор капабилити
Поле CapNo:
Добавляемая капабилити.
Удаление капабилити из набора.
17.2.2. Сведения об окружении
Эти события обычно создаются при запуске программы и описывают окружение, в котором она выполняется.
RTS_IDENTIFIER
Тег:
29
Длина:
переменная
Поле CapSetId:
Набор капабилити
Поле String:
Имя и версия системы времени выполнения.
Описывает имя и версию системы времени выполнения, отвечающей за указанный набор капабилити.
PROGRAM_ARGS
Тег:
30
Длина:
переменная
Поле CapSetId:
Набор капабилити
Поле [String]:
Аргументы командной строки, переданные программе
Описывает командную строку, использованную для запуска программы.
PROGRAM_ENV
Тег:
31
Длина:
переменная
Поле CapSetId:
Набор капабилити
Поле [String]:
Пары «имя/значение» переменных окружения. Эта строка кодируется с использованием собственной для платформы кодировки строк.
Описывает переменные окружения, доступные программе.
WALL_CLOCK_TIME
Тег:
43
Длина:
фиксированная
Поле CapSetId:
Набор капабилити
Поле Word64:
Секунды с начала эпохи Unix
Поле Word32:
Наносекунды
Записывает время по системным часам, чтобы можно было сопоставлять события из других источников с журналом событий.
17.2.3. События потоков и планирования
CREATE_THREAD
Тег:
0
Длина:
фиксированная
Поле ThreadId:
идентификатор потока
Отмечает создание потока Haskell.
RUN_THREAD
Тег:
1
Длина:
фиксированная
Поле ThreadId:
идентификатор потока
Указанный поток начал выполняться.
STOP_THREAD
Тег:
2
Длина:
фиксированная
Поле ThreadId:
идентификатор потока
Поле Word16:
состояние
1: HeapOverflow
2: StackOverflow
3: ThreadYielding
4: ThreadBlocked
5: ThreadFinished
6: ForeignCall
7: BlockedOnMVar
8: BlockedOnBlackHole
9: BlockedOnRead
10: BlockedOnWrite
11: BlockedOnDelay
12: BlockedOnSTM
13: BlockedOnDoProc
16: BlockedOnMsgThrowTo
20: BlockedOnMVarRead
Поле ThreadId:
идентификатор потока, на котором заблокирован поток (только для некоторых значений состояния)
Указанный поток прекратил выполнение по причине, обозначенной status.
Следующие события отмечают различные этапы жизненного цикла перемещающей сборки мусора.
Типичный цикл сборки мусора выглядит примерно так:
Капабилити обнаруживает необходимость сборки мусора (например, из-за исчерпания области выделения объектов) и запрашивает её. Это отмечается событием REQUEST_SEQ_GC или REQUEST_PAR_GC.
Когда остальные капабилити достигают точек передачи управления и приостанавливают выполнение, они создают события STOP_THREAD.
Когда выполнение приостановлено на всех капабилити, начинается сборка, отмеченная событием GC_START.
По мере того как отдельные потоки параллельного GC начинают сканирование, они создают события GC_WORK.
Если в потоке параллельного GC заканчивается работа, он создаёт событие GC_IDLE. Если позднее ему передадут дополнительную работу, он создаст ещё одно событие GC_WORK.
После завершения сканирования каждый поток GC создаёт событие GC_DONE.
Событие HEAP_SIZE сообщает текущий размер кучи в байтах, рассчитанный по количеству выделенных мегаблоков.
Событие BLOCKS_SIZE сообщает текущий размер кучи в байтах, рассчитанный по количеству выделенных блоков.
Событие GC_STATS_GHC содержит различные сведения о сборке и состоянии кучи.
При полной сборке событие HEAP_LIVE описывает текущий размер живых данных в куче.
В -threaded RTS создаётся событие SPARK_COUNTERS, сообщающее, сколько искр было создано, вычислено и удалено сборщиком мусора.
Когда потоки-мутаторы возобновляют выполнение, они создают события RUN_THREAD.
Событие MEM_RETURN содержит сведения о текущих активных mblock, их необходимом количестве и о том, удалось ли вернуть излишки операционной системе.
Обратите внимание: при использовании конкурентного неперемещающего сборщика во время конкурентной фазы сборки создаются дополнительные события. Они описаны в разделе События неперемещающего GC.
байт фрагментации — разница между общим размером mblock и общим размером блоков. Если все mblock полностью заполнены блоками, это значение равно 0.
Поле Word32:
количество потоков параллельного сборщика мусора
Поле Word64:
максимальное количество байт, скопированных одним потоком сборщика
Поле Word64:
общее количество байт, скопированных всеми потоками сборщика
Поле Word64:
объём сбалансированных данных, скопированных всеми потоками
Сообщает различные сведения о полной сборке.
GC_GLOBAL_SYNC
Тег:
54
Длина:
фиксированная
Это событие отмечает момент GC, когда все HEC находятся между этапами GC с остановкой мира, а все остальные HEC должны находиться между событиями GC_START и GC_END. Это позволяет сопоставить паузы GC на разных HEC с конкретной глобальной сборкой GC.
MEM_RETURN
Тег:
90
Длина:
фиксированная
Поле CapSetId:
набор капабилити кучи
Поле Word32:
текущее количество выделенных mblock
Поле Word32:
количество mblock, которое желательно сохранить
Поле Word32:
количество mblock, возвращённых операционной системе
Сообщает сведения о текущем количестве выделенных мегаблоков и попытках вернуть их операционной системе. Если куча фрагментирована, текущее значение будет больше необходимого, а возвращённое количество будет меньше разницы между ними.
17.2.5. События и статистика кучи
HEAP_ALLOCATED
Тег:
49
Длина:
фиксированная
Поле CapSetId:
набор капабилити кучи
Поле Word64:
выделено байт
Указанный набор капабилити выделил новый участок кучи.
HEAP_SIZE
Тег:
50
Длина:
фиксированная
Поле CapSetId:
набор капабилити кучи
Поле Word64:
размер кучи в байтах
Сообщает размер кучи, рассчитанный по количеству выделенных в данный момент мегаблоков.
BLOCKS_SIZE
Тег:
91
Длина:
фиксированная
Поле CapSetId:
набор капабилити кучи
Поле Word64:
размер кучи в байтах
Сообщает размер кучи, рассчитанный по количеству выделенных в данный момент блоков.
HEAP_LIVE
Тег:
51
Длина:
фиксированная
Поле CapSetId:
набор капабилити кучи
Поле Word64:
размер кучи в байтах
Сообщает размер занятой кучи.
HEAP_INFO_GHC
Тег:
52
Длина:
фиксированная
Поле CapSetId:
набор капабилити кучи
Поле Word16:
количество поколений сборки мусора
Поле Word64:
максимальный размер кучи
Поле Word64:
размер области выделения
Поле Word64:
размер MBlock
Поле Word64:
размер Block
Сообщает различные сведения о конфигурации кучи. Обычно создаётся при инициализации RTS.
17.2.6. События искр
CREATE_SPARK_THREAD
Тег:
15
Длина:
фиксированная
Создан поток для вычисления искры.
SPARK_COUNTERS
Тег:
34
Длина:
фиксированная
Периодически сообщает различные статистические данные о вычислении искр.
SPARK_CREATE
Тег:
35
Длина:
фиксированная
Искра добавлена в пул искр.
SPARK_DUD
Тег:
36
Длина:
фиксированная
Предпринята попытка создать искру для вычисления thunk, который уже был вычислен.
SPARK_OVERFLOW
Тег:
37
Длина:
фиксированная
Предпринята попытка создать искру для вычисления, когда пул искр заполнен.
SPARK_RUN
Тег:
38
Длина:
фиксированная
Начато вычисление искры.
SPARK_STEAL
Тег:
39
Длина:
фиксированная
Поле Word16:
капабилити, с которой была похищена искра
Искра похищена у другой капабилити для вычисления.
SPARK_FIZZLE
Тег:
40
Длина:
фиксированная
Искра удалена сборщиком мусора до начала вычисления.
SPARK_GC
Тег:
41
Длина:
фиксированная
Невычисленная искра собрана сборщиком мусора.
17.2.7. События возможностей
CAP_CREATE
Тег:
45
Длина:
фиксированная
Поле CapNo:
номер возможности
Возможность была запущена.
CAP_DELETE
Тег:
46
Длина:
фиксированная
Возможность была удалена.
CAP_DISABLE
Тег:
47
Длина:
фиксированная
Возможность была отключена.
CAP_ENABLE
Тег:
48
Длина:
фиксированная
Возможность была включена.
17.2.8. События задач
TASK_CREATE
Тег:
55
Длина:
фиксированная
Поле TaskId:
идентификатор задачи
Поле CapNo:
номер возможности
Поле KernelThreadId:
Идентификатор потока ядра, создавшего задачу.
Отмечает создание задачи.
TASK_MIGRATE
Тег:
56
Длина:
фиксированная
Поле TaskId:
идентификатор задачи
Поле CapNo:
прежняя возможность
Поле CapNo:
новая возможность
Отмечает перенос задачи в новую возможность.
TASK_DELETE
Тег:
57
Длина:
фиксированная
Поле TaskId:
идентификатор задачи
Отмечает удаление задачи.
17.2.9. События трассировки
LOG_MSG
Тег:
16
Длина:
переменная
Поле String:
сообщение
Сообщение журнала от системы времени выполнения.
BLOCK_MARKER
Тег:
18
Длина:
фиксированная
Поле Word32:
размер блока
Поле Word64:
время окончания в наносекундах
Поле Word16:
номер возможности, недействителен, если 0xffff.
Отмечает фрагмент событий. Все события, помещающиеся в следующие block size байт, относятся к возможности маркера блока.
17.3. Вывод событий профилировщика кучи в журнал событий
Профилировщик кучи может записывать данные в журнал событий GHC, что позволяет сопоставлять выборки с другими событиями журнала на протяжении жизненного цикла программы.
В этом разделе описан формат этих событий. Тип String ниже определяется как строка UTF-8 с завершающим нулевым байтом.
17.3.1. Типы событий метаданных
17.3.1.1. Начало потока выборок
Одно событие фиксированной ширины, выдаваемое при запуске программы и описывающее последующие выборки.
Пакет переменной длины, формируемый один раз для каждого центра затрат:
HEAP_PROF_COST_CENTRE
Тег:
161
Длина:
фиксированная
Поле Word32:
номер центра затрат
Поле String:
метка
Поле String:
модуль
Поле String:
местоположение в исходном коде
Поле Word8:
флаги:
бит 0: является ли центр затрат CAF?
17.3.1.3. Определения происхождения таблиц информации
Сообщение с приблизительным исходным местоположением таблиц информации. Дополнительные сведения см. в разделе -finfo-table-map.
IPE
Тег:
169
Длина:
фиксированная
Поле Word64:
адрес таблицы информации
Поле String:
имя таблицы
Поле String:
тип замыкания
Поле String:
тип
Поле String:
метка исходной позиции
Поле String:
модуль исходной позиции
Поле String:
местоположение исходной позиции
17.3.1.4. Типы событий выборок
Выборка (состоящая из списка классов разбиения, например центров затрат, и размеров занятой кучи) кодируется в теле одного или нескольких событий.
Обычно начало новой выборки помечается событием EVENT_HEAP_PROF_SAMPLE_BEGIN:
HEAP_PROF_SAMPLE_BEGIN
Длина:
фиксированная
Поле Word64:
номер выборки
Отмечает начало выборки профиля кучи.
Выборки биографического профилирования начинаются с события EVENT_HEAP_BIO_PROF_SAMPLE_BEGIN. Эти события также содержат временную метку, указывающую, когда была сделана выборка. Это необходимо, поскольку из-за особенностей работы режима биографического профилирования все эти выборки будут находиться в конце журнала событий. Временную метку можно использовать, чтобы расположить выборки относительно других событий.
HEAP_BIO_PROF_SAMPLE_BEGIN
Тег:
166
Длина:
фиксированная
Поле Word64:
номер выборки
Поле Word64:
временная метка журнала событий в нс
Далее следует перепись занятой кучи. Поскольку длина событий не может превышать 2^16^ байт, одну выборку может потребоваться разбить на несколько событий EVENT_HEAP_PROF_SAMPLE. Точный формат записей переписи определяется типом разбиения.
В конце периода выборки выдаётся событие EVENT_HEAP_PROF_SAMPLE_END. Оно позволяет правильно обозначить границы периода выборки и записать общее время профилирования.
HEAP_PROF_SAMPLE_END
Тег:
165
Длина:
фиксированная
Поле Word64:
номер выборки
Отмечает конец выборки профиля кучи.
17.3.1.5. Разбиение по центрам затрат
Пакет переменной длины, кодирующий выборку профиля кучи с разбиением по:
17.4. Вывод событий профилировщика времени в журнал событий
Режим временного профилирования, включаемый с помощью -p, также записывает события выборок в журнал событий. В начале профилирования в журнал событий записывается интервал тиков, а затем при каждом тике — текущий стек центров затрат. Вместе это позволяет пользователю построить приблизительную картину выполнения программы.
Эти события обозначают различные этапы жизненного цикла non-moving collection. Они включаются набором событий +RTS -lg.
Типичный цикл сборки неподвижного сборщика будет выглядеть примерно так:
На подготовительном этапе сборки будут выведены обычные события, связанные с перемещающей сборкой. Подробности см. в разделе События сборщика мусора.
Включается конкурентный барьер записи и запускается поток конкурентной маркировки. С этого момента потоки-мутаторы могут генерировать события CONC_UPD_REM_SET_FLUSH, указывающие на то, что они сбросили локальные для своих capabilities наборы запоминания обновлений.
Начинается конкурентная маркировка, о чём сообщает событие CONC_MARK_BEGIN.
Когда очередь маркировки опустеет, будет выведено событие CONC_MARK_END.
При необходимости (например, из-за маркировки слабых указателей) процесс маркировки продолжится, вернувшись к шагу (3) выше.
Когда сборщик выполнит всю возможную конкурентную маркировку, он перейдёт к этапу синхронизации после маркировки, обозначенному событием CONC_SYNC_BEGIN.
Потоки-мутаторы приостановят выполнение и при необходимости сбросят свои наборы запоминания обновлений (что обозначается событиями CONC_UPD_REM_SET_FLUSH).
Сборщик выполнит всю необходимую заключительную маркировку (что обозначается событиями CONC_MARK_BEGIN и CONC_MARK_END).
Сборщик выполнит небольшую часть очистки, отключит барьер записи, выведет событие CONC_SYNC_END и позволит мутаторам продолжить выполнение.
Сборщик начнёт этап конкурентной очистки, обозначенный событием CONC_SWEEP_BEGIN.
После завершения очистки будет выведено событие CONC_SWEEP_END, а поток конкурентного сборщика завершится.
Будет выведено событие NONMOVING_HEAP_CENSUS с описанием состояния фрагментации неподвижной кучи.
Обозначает начало маркировки конкурентным сборщиком.
CONC_MARK_END
Тег:
201
Длина:
фиксированная
Поле Word32:
количество объектов, помеченных на этом этапе маркировки.
Обозначает конец маркировки конкурентным сборщиком.
CONC_SYNC_BEGIN
Тег:
202
Длина:
фиксированная
Обозначает начало этапа синхронизации конкурентного сборщика мусора после маркировки.
CONC_SYNC_END
Тег:
203
Длина:
фиксированная
Обозначает конец этапа синхронизации конкурентного сборщика мусора после маркировки.
CONC_SWEEP_BEGIN
Тег:
204
Длина:
фиксированная
Обозначает начало этапа конкурентной очистки сборщика мусора.
CONC_SWEEP_END
Тег:
205
Длина:
фиксированная
Обозначает конец этапа конкурентной очистки сборщика мусора.
CONC_UPD_REM_SET_FLUSH
Тег:
206
Длина:
фиксированная
Обозначает сброс capability своего локального аккумулятора набора запоминания обновлений.
17.6.1. Перепись неподвижной кучи
События переписи неподвижной кучи (включаемые набором событий +RTS -ln) предназначены для анализа фрагментации неподвижной кучи.
NONMOVING_HEAP_CENSUS
Тег:
207
Длина:
фиксированная
Поле Word16:
blk_sz в байтах.
Поле Word32:
количество активных сегментов.
Поле Word32:
количество заполненных сегментов.
Поле Word32:
количество живых блоков.
Описывает заполненность подобласти кучи blk_sz.
NONMOVING_PRUNED_SEGMENTS
Тег:
208
Длина:
фиксированная
Поле Word32:
количество удалённых сегментов.
Поле Word32:
количество сегментов, оставшихся в списке свободных сегментов.
Сообщает количество удалённых сегментов и количество сегментов, оставшихся в списке свободных сегментов неподвижной кучи. Сегменты сохраняются в списке свободных сегментов, пока не станет возможным освободить весь содержащий их мегаблок.
17.6.2. Счётчики Ticky
Программы, скомпилированные с -ticky и -eventlog и запущенные с +RTS -lT, будут периодически записывать в журнал событий значения счётчиков входов Ticky.
TICKY_COUNTER_DEF
Тег:
210
Длина:
переменная
Поле Word64:
идентификатор счётчика
Поле Word16:
арность/количество полей
Поле String:
виды аргументов. Это то же поле, что и одноимённое поле в текстовой сводке Ticky.
Поле String:
имя счётчика
Поле Word64:
адрес информационной таблицы
Поле String:
информация о счётчике в формате JSON
Определяет счётчик Ticky.
TICKY_COUNTER_BEGIN_SAMPLE
Тег:
212
Длина:
фиксированная
Обозначает начало атомарного набора выборок счётчиков профилировщика Ticky-Ticky.
TICKY_COUNTER_SAMPLE
Тег:
211
Длина:
фиксированная
Поле Word64:
идентификатор счётчика
Поле Word64:
количество входов в замыкания этого типа.
Поле Word64:
количество выделений памяти (слов)
Поле Word64:
количество выделенных слов. Выводится только для модулей, скомпилированных с -ticky-allocd.
Записывает количество «тиков», зарегистрированных счётчиком Ticky-Ticky с момента последней выборки.