В этом разделе описываются кодировки событий, генерируемых журналом событий GHC. Эти события могут содержать информацию о планировании потоков, статистике сборки мусора, информации о профилировании, событиях отслеживания, заданных пользователем.
Этот раздел предназначен для разработчиков инструментов, которые потребляют эти события. GHC поставляется с файлом заголовков C (EventlogFormat.h), который предоставляет символические имена для идентификаторов типов событий, описанных в этом файле.
17.1. Формат журнала событий
Формат журнала спроектирован для расширяемости: старые инструменты должны уметь парсить (но необязательно понимать всё) новые версии формата, а новые инструменты смогут понимать старые файлы журнала.
Формат независим от порядка байтов: все значения представлены в формате big-endian.
Формат расширяемый:
Заголовок описывает каждый тип события и его длину. Инструменты, не распознающие определённый тип события, могут пропустить эти события.
В спецификации типа события есть место для дополнительной информации, которую могут игнорировать более старые инструменты.
К событиям можно добавлять дополнительную информацию, но существующие поля изменять нельзя. Инструменты должны игнорировать дополнительные поля в конце записи события.
Поток журнала событий начинается с заголовка, описывающего типы событий (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. Наборы возможностей
TODO
17.2.2. Информация об окружении
Эти события обычно генерируются во время запуска программы и описывают среду, в которой запускается программа.
RTS_IDENTIFIER
Тег:
29
Длина:
переменная
Поле CapSetId:
Набор возможностей
Поле String:
Имя и версия системы выполнения.
Описывает имя и версию системы выполнения, отвечающей за указанный набор возможностей.
PROGRAM_ARGS
Тег:
30
Длина:
переменная
Поле CapSetId:
Набор возможностей
Поле [String]:
Аргументы командной строки, переданные программе
Описывает командную строку, используемую для запуска программы.
PROGRAM_ENV
Тег:
31
Длина:
переменная
Поле CapSetId:
Набор возможностей
Поле [String]:
Наборы пар «имя переменной окружения/значение». (TODO: кодировка?)
Описывает переменные окружения, присутствующие в среде программы.
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.
THREAD_RUNNABLE
Тег:
3
Длина:
фиксированная
Поле ThreadId:
идентификатор потока
Указанный поток помечен как готовый к запуску.
MIGRATE_THREAD
Тег:
4
Длина:
фиксированная
Поле ThreadId:
идентификатор потока
Поле CapNo:
возможность
Указанный поток был перемещён в новую возможность.
THREAD_WAKEUP
Тег:
8
Длина:
фиксированная
Поле ThreadId:
идентификатор потока
Поле CapNo:
другая возможность
Указанный поток был разбужен другой возможностью.
THREAD_LABEL
Тег:
44
Длина:
переменная
Поле ThreadId:
идентификатор потока
Поле String:
метка
Указанному потоку была присвоена метка (например, с помощью GHC.Conc.labelThread).
17.2.4. События сборщика мусора
Следующие события отмечают различные моменты жизненного цикла движущейся сборки мусора.
Типичный цикл сборки мусора выглядит следующим образом:
Возможность понимает, что ей необходима сборка мусора (например, в результате исчерпания ячейки) и запрашивает её. Это отмечается событием REQUEST_SEQ_GC или REQUEST_PAR_GC.
По мере того, как другие возможности достигают точек отдачи и приостанавливают выполнение, они генерируют события STOP_THREAD.
Когда все возможности приостановят выполнение, начнется сборка, отмеченная событием GC_START.
По мере того, как отдельные параллельные потоки GC начинают сканирование, они генерируют события GC_WORK.
Если у параллельного потока GC закончилась работа, он генерирует событие GC_IDLE. Если позже ему снова будет передана работа, он генерирует другое событие GC_WORK.
В конечном итоге, по завершении сканирования каждый поток GC сгенерирует событие GC_DONE.
Выполняется немного учёта.
Событие GC_END будет генерироваться, отмечая конец цикла GC.
Событие HEAP_SIZE будет сгенерировано, указывая текущий размер кучи в байтах, вычисленный по количеству выделенных мегаблоков.
Событие BLOCKS_SIZE будет сгенерировано, указывая текущий размер кучи в байтах, вычисленный по количеству выделенных блоков.
Событие GC_STATS_GHC будет генерироваться, содержащее различные детали о состоянии сборки и кучи.
В случае основной сборки будет генерироваться событие HEAP_LIVE, описывающее текущий размер активных данных в куче.
В случае RTS -threaded будет генерироваться событие SPARK_COUNTERS, предоставляющее информацию о количестве созданных, обработанных и собранных GC искр.
По мере возобновления выполнения потоков мутаторов они будут генерировать события RUN_THREAD.
Событие MEM_RETURN будет генерироваться, содержащее подробности о текущих активных mблоках, о том, сколько, по нашему мнению, нам нужно, и о возможности возврата избыточных ресурсов операционной системе.
Обратите внимание, что в случае конкурирующего неперемещаемого сборщика мусора дополнительные события будут генерироваться во время конкурентной фазы сборки. Они описаны в Выводе событий неперемещаемого GC.
GC_START
Тэг:
9
Длина:
фиксированная
Начался проход сборки мусора.
GC_END
Тэг:
10
Длина:
фиксированная
Закончен проход сборки мусора.
REQUEST_SEQ_GC
Тэг:
11
Длина:
фиксированная
Возможность запросила последовательную сборку мусора.
REQUEST_PAR_GC
Тэг:
12
Длина:
фиксированная
Возможность запросила параллельную сборку мусора.
GC_IDLE
Тэг:
20
Длина:
фиксированная
Началась сборка мусора в режиме простоя.
GC_WORK
Тэг:
21
Длина:
фиксированная
Отмечает начало конкурентного сканирования.
GC_DONE
Тэг:
22
Длина:
фиксированная
Отмечает конец конкурентного сканирования.
GC_STATS_GHC
Тэг:
53
Длина:
фиксированная
Поле CapSetId:
набор возможностей кучи
Поле Word16:
поколение сборки
Поле Word64:
скопированные байты
Поле Word64:
найденные байты лишних данных
Поле Word64:
байты фрагментации, разница между общим размером mблоков и общим размером блоков. Когда все mблоки заполнены полными блоками, это число равно 0.
Поле Word32:
количество параллельных потоков сборки мусора
Поле Word64:
максимальное количество байтов, скопированных одним потоком сборщика
Поле Word64:
общее количество байтов, скопированных всеми потоками сборщиков
Поле Word64:
количество скопированных сбалансированных данных всеми потоками
Отчёт о различных данных о крупной сборке.
GC_GLOBAL_SYNC
Тэг:
54
Длина:
фиксированная
TODO
MEM_RETURN
Тэг:
90
Длина:
фиксированная
Поле CapSetId:
набор возможностей кучи
Поле Word32:
текущие выделенные mблоки
Поле Word32:
количество mблоков, которые мы хотим сохранить
Поле Word32:
количество mблоков, возвращённых операционной системе
Отчёт об информации о текущем выделении мегаблоков и попытках вернуть их операционной системе. Если ваша куча фрагментирована, то текущее значение будет больше, чем необходимое, а возвращённое значение будет меньше разницы между ними.
17.2.5. События и статистика кучи
HEAP_ALLOCATED
Тэг:
49
Длина:
фиксированная
Идентификатор набора свойств кучи:
набор свойств кучи
Слово 64 бита:
выделенные байты
Новый фрагмент кучи был выделен указанным набором свойств.
HEAP_SIZE
Тэг:
50
Длина:
фиксированная
Идентификатор набора свойств кучи:
набор свойств кучи
Слово 64 бита:
размер кучи в байтах
Сообщается о размере кучи, рассчитанном по количеству используемых мегаблоков.
BLOCKS_SIZE
Тэг:
91
Длина:
фиксированная
Идентификатор набора свойств кучи:
набор свойств кучи
Слово 64 бита:
размер кучи в байтах
Сообщается о размере кучи, рассчитанном по количеству используемых блоков.
HEAP_LIVE
Тэг:
51
Длина:
фиксированная
Идентификатор набора свойств кучи:
набор свойств кучи
Слово 64 бита:
размер активной кучи в байтах
Сообщается о размере активной кучи.
HEAP_INFO_GHC
Тэг:
52
Длина:
фиксированная
Идентификатор набора свойств кучи:
набор свойств кучи
Слово 16 бит:
количество поколений сборки мусора
Слово 64 бита:
максимальный размер кучи
Слово 64 бита:
размер области выделения
Слово 64 бита:
размер MBlock
Слово 64 бита:
размер блока
Сообщается о различных параметрах конфигурации кучи. Обычно генерируется во время инициализации RTS.
17.2.6. События Spark
CREATE_SPARK_THREAD
Тэг:
15
Длина:
фиксированная
Создан поток для выполнения вычислений Spark.
SPARK_COUNTERS
Тэг:
34
Длина:
фиксированная
Периодическое предоставление различных статистических данных о вычислениях Spark.
SPARK_CREATE
Тэг:
35
Длина:
фиксированная
Spark добавлен в пул Spark.
SPARK_DUD
Тэг:
36
Длина:
фиксированная
TODO
SPARK_OVERFLOW
Тэг:
37
Длина:
фиксированная
TODO
SPARK_RUN
Тэг:
38
Длина:
фиксированная
Начато выполнение на Spark.
SPARK_STEAL
Тэг:
39
Длина:
фиксированная
Слово 16 бит:
свойство, из которого был украден Spark
Spark был украден из другого свойства для выполнения.
SPARK_FIZZLE
Тэг:
40
Длина:
фиксированная
Spark был удален сборкой мусора до выполнения.
SPARK_GC
Тэг:
41
Длина:
фиксированная
Невыполненый Spark был удален сборкой мусора.
17.2.7. События свойств
CAP_CREATE
Тэг:
45
Длина:
фиксированная
Номер свойства:
номер свойства
Свойство запущено.
CAP_DELETE
Тэг:
46
Длина:
фиксированная
Свойство удалено.
CAP_DISABLE
Тэг:
47
Длина:
фиксированная
Свойство отключено.
CAP_ENABLE
Тэг:
48
Длина:
фиксированная
Свойство включено.
17.2.8. События задач
TASK_CREATE
Тег:
55
Длина:
фиксированная
Поле TaskId:
id задачи
Поле CapNo:
номер возможности
Поле KernelThreadId:
Идентификатор потока ядра, создавшего задачу.
Помечает создание задачи.
TASK_MIGRATE
Тег:
56
Длина:
фиксированная
Поле TaskId:
id задачи
Поле CapNo:
старая возможность
Поле CapNo:
новая возможность
Помечает перемещение задачи в новую возможность.
TASK_DELETE
Тег:
57
Длина:
фиксированная
Поле TaskId:
id задачи
Помечает удаление задачи.
17.2.9. События трассировки
LOG_MSG
Тег:
16
Длина:
переменная
Поле String:
сообщение
Сообщение журнала от системы выполнения.
BLOCK_MARKER
Тег:
18
Длина:
фиксированная
Поле Word32:
размер блока
Поле Word64:
время окончания в наносекундах
Поле Word16:
номер возможности, недействительно, если 0xffff.
Помечает блок событий. Все события, помещающиеся в следующие block size байт, относятся к блоку маркера возможности.
Профилировщик кучи может генерировать вывод в журнал событий 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. Это полезно для правильного разграничения периода выборки и записи общего времени, затраченного на профилирование.
17.4. Вывод журнала событий профилировщика времени
Режим профилирования времени, включенный с помощью -p, также отправляет образцы событий в журнал событий. В начале профилирования интервал тиков отправляется в журнал событий, а затем при каждом тике отправляется текущий стек центра затрат. Вместе они позволяют пользователю построить приблизительный путь выполнения их программы.
Эти события отмечают различные стадии жизненного цикла non-moving collection. Они включаются набором событий +RTS -lg.
Типичный цикл неперемещающего сбора мусора будет выглядеть примерно следующим образом:
Фаза подготовки сбора выведет обычные события, связанные с перемещающим сбором. Подробности см. в разделе События сборщика мусора.
Включается конкурентная помеченная метка и запускается поток конкуретного маркирования. С этого момента потоки мутаторов могут генерировать события CONC_UPD_REM_SET_FLUSH, указывая, что они очистили свои локальные наборы запоминающихся обновлений.
Начинается конкурентное маркирование, обозначенное событием CONC_MARK_BEGIN.
Когда очередь маркирования становится пустой, генерируется событие CONC_MARK_END.
При необходимости (например, из-за маркирования слабых ссылок) процесс маркирования продолжится, возвращаясь к шагу (3) выше.
Когда сборщик выполнил как можно больше конкуретного маркирования, он переходит к фазе постмаркировочной синхронизации сбора, обозначенной событием CONC_SYNC_BEGIN.
Потоки мутаторов приостанавливают выполнение и, при необходимости, очищают свои наборы запоминающихся обновлений (указано событиями CONC_UPD_REM_SET_FLUSH).
События переписи неперемещаемой кучи (включенные с помощью +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:
ID счётчика
Поле Word16:
арность/количество полей
Поле String:
типы аргументов. Это то же самое, что и синонимичное поле в текстовом сводке ticky.
Поле String:
имя счётчика
Поле Word64:
адрес таблицы с информацией
Поле String:
информация о счётчике в формате JSON
Определяет счётчик ticky.
TICKY_COUNTER_BEGIN_SAMPLE
Тег:
212
Длина:
фиксированная
Обозначает начало набора выборок счётчиков профилировщика ticky-ticky в атомарном формате.
TICKY_COUNTER_SAMPLE
Тег:
211
Длина:
фиксированная
Поле Word64:
ID счётчика
Поле Word64:
количество входов в замыкания данного типа.
Поле Word64:
количество выделений (слов)
Поле Word64:
количество выделений (слов) в данном случае. Выводится только для модулей, скомпилированных с -ticky-allocd.
Записывает количество «тика» (ticks), зарегистрированных счётчиком ticky-ticky за последние выборки.