← На главную

Вышел PawPrint — детерминированный .NET runtime против race conditions

04.06.2026 07:32 · hackernews

Вышла ранняя версия WoofWare.PawPrint — детерминированного .NET runtime, который автор выложил на NuGet. Эта штука работает как CHESS для .NET: интерпретирует IL, вырезая только JIT-интринсики и нативный код из BCL, и не использует никаких сокращений. Уже умеет выполнять Console.WriteLine, async void Main с аргументами, Task.Run, кучу рефлексии и низкоуровневые примитивы синхронизации вроде Monitor.

Для планирования потоков PawPrint использует вариант Probabilistic Concurrency Testing — пытается перебрать как можно больше «интересных» перестановок потоков. Автор проверил это на шести стандартных race conditions: каждый тест находил баг почти сразу, часто с первой же попытки.

Но запускать это в продакшн пока рано — скорее всего, упадёт сразу. BCL полна нативного кода, и каждую такую функцию в PawPrint нужно явно моделировать. В планах — дать пользователям возможность подключать свои реализации, чтобы не упираться в ограничения встроенной поддержки.

Внутренняя архитектура очень богатая. PawPrint отслеживает всё происхождение данных: каждый указатель знает, на какой объект/поле/метод он смотрит. Каждый байтовый массив помнит, является ли он проекцией объекта в сырые байты или просто набором байтов. Результаты арифметических операций тоже хранят свой смысл — сумма целых чисел, разница указателей внутри одного массива и так далее. Это заточено под time-travel debugging и полный контроль над историей выполнения.

Исходный дизайн автор писал вручную. Потом вышла Sonnet 4.6, и он начал использовать её как справочник по .NET. Gemini 2 Pro помогал с fuzzy-поиском по ECMA-335. А в 2026 году случилась «LLM-психоз» — автор бросил Claude Opus 4.6/7 и GPT-5.5 на «доработку» проекта. Это ускорило разработку на годы, но сделало код «форм-фактора Claude» на микроуровне. Единственное крупное архитектурное решение, которое автор полностью передоверил GPT-5.5 из лени, обернулось катастрофой. Модель решила представлять массивы как расположенные в фиктивных адресах памяти, что привело к потере провенанса при арифметике. Автор выбросил эту реализацию и переписал вручную — теперь адреса объектов помечаются синтетическими маркерами, и арифметика на них ломает PawPrint. Но это нормально: .NET сам не определяет поведение для таких чисел.

Читать оригинал →