Дважды за один замер врал прибор, а не предмет — и оба раза это выглядело как находка
В замере пути в WebAssembly два «расхождения» оказались дефектами самого замера, и оба выглядели убедительно: с числами, воспроизводимо, в нужную сторону.
Первое. Прогонщик отдавал вывод модуля через трубу, а node:wasi пишет в трубу асинхронно и обрывает хвост. Восемь прогонов одного и того же модуля дали 171 819 байт пять раз и 158 167, 163 072, 166 220 остальные три; обычный бинарник давал 171 819 все восемь раз. Читалось это как «wasm искажает вывод» — то есть ровно как то, что замер и должен был найти.
Второе. Проба потолка памяти намеряла «16 ГиБ» в 32-битном адресном пространстве. Счётчик был size_t, а он на wasm32 32-битный, и 6.4 ГиБ завернулись через 2³². Хуже: malloc в wasi-libc после исчерпания адресного пространства продолжает выдавать указатели, и они перекрываются, — то есть проба верила malloc != NULL, а проверять надо было метку на каждом куске.
Общее у обоих: прибор врал в ту сторону, которую замер и ожидал увидеть. Правдоподобный результат — не признак правильного измерения, а самый опасный случай, потому что его не перепроверяют. Отсюда рабочее правило: прежде чем называть расхождение находкой, надо прогнать одно и то же несколько раз и сверить прибор с заведомо известным ответом.
Чем подтверждено. Ветка work/wasm-cherez-c, коммиты «Обрыв вывода был в прогоннике…» и «Стена стандартного ввода оказалась в Node…», отчёт docs/wasm-via-c.md. Первое поймано повтором одного прогона восемь раз; чинится тем, что код возврата ставится полем, а не process.exit(), и что вывод забирается через файл (10 прогонов из 10 по 171 819 байт). Второе поймано тем, что число не сошлось с арифметикой: 401 кусок по 16 МиБ не может дать 2320 МиБ. Исправленная проба даёт честные 4080.1 МиБ (65 282 страницы).
Третий случай в том же замере оказался НЕ прибором, и различить помогла та же дисциплина: отказ «неразборчивые аргументы» на крупном вводе сначала выглядел как наш дефект, но тот же вход из файла проходил, правка в C не помогала, а wasmtime не терял ничего — значит виноват хозяин, node:wasi, и чинить в дереве нечего.
Чем ограничено. Это не довод против измерений, а требование к ним: у прибора должна быть своя проверка. Дешёвых проверок здесь две — повтор одного и того же прогона (ловит недетерминированность) и сверка арифметики результата с самой собой (ловит переполнение и потерю данных).
Связано: wasm-via-c-is-free, checks-that-stopped-comparing, checksum-inside-the-benchmark, byte-for-byte-comparison