openlang

try против catch unreachable в горячем цикле, цифры не сходятся

Замеряю try parseLine(line) против parseLine(line) catch unreachable на ~2M сгенерированных строк вида ts,level,bytes, суммирую bytes. Собрано с -Doptimize=ReleaseFast.

Прогон с try показывает несколько сотен микросекунд и вместо итоговой суммы печатает имя ошибки. Прогон с catch unreachable занимает десятки мс, и итог другой. ReleaseSafe и Debug на втором паникуют. Я добавил битую строку каждые 5000 строк, чтобы "было поближе к реальности". С --bad-every 0 всё выглядит адекватнее, но я не понимаю, почему это так сильно влияет.

Два цикла:

const e = try parse.parseLine(line);
total += e.bytes;
// vs
const e = parse.parseLine(line) catch unreachable;
total += e.bytes;

Мои догадки: error return traces или инлайнинг. В ассемблер пока не смотрел. Генерация входных данных уже вне таймера. (splitScalar появился примерно в 0.12, кажется, но если я ошибаюсь, не обращайте внимания.)

Так что же это на самом деле измеряет? Спасибо за любые подсказки.

Переведено с английскогоПоказать оригинал

Разговор продолжается 2

Следуя доводам
  1. Ссылка на ответ

    Вы сравниваете не два способа обработки одной и той же работы. Прогон с try выходит на первой же битой строке. Несколько сотен µs на 2M строк означает, что цикл едва успел начаться, а имя ошибки, которое вы видите, относится к этому раннему возврату. Если в генераторе i % 5000 == 0, то строка 0 уже битая, так что он падает сразу.

    Прогон с catch unreachable — отдельная история. В ReleaseFast это undefined behaviour на первой же битой строке, так что оптимизатор может делать что угодно. Поэтому и сумма не сходится. Debug и ReleaseSafe паникуют, потому что реально проверяют. Десяткам мс тоже нельзя доверять, ведь компилятор мог свернуть цикл во что-то странное.

    Я бы сначала прогнал бенч с нулём битых строк, а потом с битыми, обработанными через catch continue или счётчик. И сравнил бы их. Выводите вместе с суммой, сколько строк реально распарсено, чтобы знать, что цикл дошёл до конца.

    Честно говоря, мне это похоже на какую-то причуду кодгена, так что проверьте ещё версию Zig. На какой сборке вы сидите?

    Переведено с английскогоПоказать оригинал

Другие стороны того же вопроса

  1. простые циклы очень медленные, gfortran, массив 200000 x 64

    Небольшая утилита для калибровки, код ниже. Результат правильный, но слишком медленно. detrend+clip занимает несколько секунд…

    Ответы 2Последняя активность fortran
  2. running_mean тормозит, время уходит на memmove, а не на арифметику

    Сглаживаю данные датчиков. Массив readings(nstation, ntime), станция первым индексом, потому что так устроен файл с данными и…

    Ответы 1Последняя активность fortran
  3. Какое время сборки вы приводите?

    Каждая тема про разбиение крейтов заканчивается тем, что кто-то выкладывает одно время сборки. Чисел два, и меняются они в ра…

    Ответы 2Последняя активность rust