Facebook опубликовал Hermit, инструментарий для повторяемого выполнения программ

Facebook (запрещён в РФ) опубликовал код инструментария Hermit, формирующего окружение для детерминированного выполнения программ, позволяющее при разных запусках добиться получения неизменного результата и повторения хода выполнения при использовании одних и тех же входных данных. Код проекта написан на языке Rust и распространяется под лицензией BSD.

При обычном выполнении на результат влияют разнообразные посторонние факторы, такие как текущее время, особенности планирования выполнения потоков, адреса виртуальной памяти, данные от генератора псевдослучайных чисел и различные уникальные идентификаторы. Hermit позволяет запустить программу в контейнере, в котором данные факторы остаются постоянными при последующих запусках. Повторяемое выполнение, при котором полностью воспроизводятся непостоянные параметры окружения, может применяться для диагностики ошибок, многоэтапной отладки с повторными запусками, создания фиксированного окружения для проведения регрессионных тестов, стресс-тестирования, выявления проблем с многопоточностью и в системах повторяемых сборок.


Воспроизводимое окружение создаётся через перехват системных вызовов, часть из которых подменяется на собственные обработчики, выдающие постоянный результат, а часть перенаправляется в ядро, после чего результат очищается от непостоянных данных. Для перехвата системных вызовов применяется фреймворк reverie, код которого также опубликован компанией Facebook. Для предотвращения влияния на ход исполнения изменений в файловой системе и сетевых запросов, выполнение производится с использованием фиксированного образа ФС и с отключением доступа к внешним сетям. При обращении к генератору псевдослучайных чисел Hermit выдаёт предопределённую последовательность, повторяющуюся при каждом запуске.

Из наиболее сложных непостоянных влияний на ход выполнения выделяется планировщик потоков, поведение которого зависит от многих внешних факторов, таких как число ядер CPU и наличие других выполняемых потоков. Для обеспечения повторяемости поведения планировщика все потоки выполняются сериализованно в привязке только к одному ядру CPU и с сохранением порядка передачи управления потокам. Каждому потоку разрешено выполнить фиксированное число инструкций, после чего исполнение останавливается и передаётся другому потоку (для ограничения используется блок CPU PMU (Performance Monitoring Unit), останавливающий исполнение после заданного числа условных ветвлений).

Для диагностики проблем с потоками из-за возникновения состояния гонки в Hermit имеется режим выявления операций, порядок выполнения которых был нарушен и привёл к аварийному завершению работы. Для выявления подобных проблем осуществляется сравнение состояний, при которых фиксировалась корректная работа и аварийное завершение выполнения.

Release. Ссылка here.