Hacker News Digest

Тег: #compiler-optimization

Постов: 5

Error ABI (matklad.github.io)

Статья рассматривает проблемы ABI (Application Binary Interface) при обработке ошибок в программировании. Распространённое мнение, что заполнение информации об ошибках "бесплатно" из-за их редкости, неверно. Наивное составление ошибок из алгебраических типов данных (ADT) ухудшает "счастливый путь" выполнения кода. Объекты ошибок, рекурсивно составленные из перечислений, tend to be large, увеличивая size_of<Result<T, E>>, что заставляет функции по всей стеку вызовов использовать возврат больших структур через память. "Вирусность" ошибок означает, что даже одна большая ошибка на редко выполняемом пути ухудшает производительность везде.

Поэтому зрелые библиотеки обработки ошибок скрывают их за тонким указателем, как в Rust (failure и anyhow), но это требует глобального аллокатора, что тоже не бесплатно. Автор предлагает три подхода к возврату результатов: стандартный (как пользовательский тип), более умный (ABI как у T с зарезервированным регистром для E) и радикальный (полное совпадение ABI с -> T и разворот стека для ошибок). Последний, по мнению автора, может быть оптимальным, несмотря на отсутствие надёжных бенчмарков. Вывод: обработка ошибок должна быть специальной для компилятора, особенно в языках со средним уровнем абстракций.

by todsacerdoti • 10 ноября 2025 г. в 02:31 • 79 points

ОригиналHN

#abi#rust#error-handling#performance-optimization#algebraic-data-types#compiler-optimization#memory-allocation#java

Комментарии (31)

  • Адаптивные ABI для статически линкуемых программ могут оптимизировать производительность за счёт контекстного анализа использования функций.
  • Проблема "вирусности" больших типов ошибок: даже редкие большие ошибки могут ухудшить производительность всего стека вызовов.
  • Альтернативные подходы к обработке ошибок включают тонкие указатели с vtable (anyhow/failure) и разделение Result<T,E> при значительном различии размеров T и E.
  • Добавление исключений в Rust вызывает споры: одни видят в этом угрозу производительности, другие — потенциальное решение проблем обработки ошибок.
  • Checked exceptions в Java критикуют за необходимость изменения кода при модификации исключений, хотя другие видят в этом преимущество для надёжности кода.

When Compiler Optimizations Hurt Performance (nemanjatrifunovic.substack.com)

by rbanffy • 14 октября 2025 г. в 09:49 • 75 points

ОригиналHN

#compiler-optimization#performance#cpu#memory

Комментарии (26)

  • Современные компиляторы умеют как микро-, так и макро-оптимизации, но между ними остаётся «запретная зона», где оптимизация неэффективна из-за сложной модели стоимости операций в памяти и ветвлениях.
  • Пример: вместо векторизации циклов компилятор может вставить rep movsb, что на старом CPU быстрее, но на новом медленнее.
  • Практический вывод: измеряйте, прежде чем оптимизировать; не верьте мифам о «магии» компилятора.

Contracts for C (gustedt.wordpress.com)

Контракты для C  
C++ почти утвердила контракты (P2900); я попробовал адаптировать идеи для C.  
Пока это черновик, без реализации в компиляторах.

Главное:  
- `pre`/`post` — проверяемые условия на входе/выходе функции.  
- Не ломают ABI.  
- Компонуются и позволяют оптимизатору выкинуть лишние проверки.  
- Если условие — константа, оно как `static_assert`: ошибка компиляции.

Базовые примитивы  
```c
contract_assert(условие, "текст");   // всегда проверяется, при лжи — abort
contract_assume(условие, "текст");   // компилятор верит, иначе UB

Пример функции

// заголовок
void *my_malloc(size_t s) pre(s) post(r: r);

// реализация
inline void *my_malloc(size_t s) {
    contract_assert(s, "size != 0");
    defer { contract_assert(defer_return_value, "ok"); };
    return malloc(s);
}

defer выполняет post-проверку при любом выходе.
Инлайн даёт компилятору видеть контракт; внешняя декларация сохраняет привычное разделение .h/.c.

Польза: читаемость, статический анализ, оптимизация.

by joexbayer • 05 сентября 2025 г. в 06:36 • 95 points

ОригиналHN

#c#c++#contracts#programming-languages#compiler-optimization#static-analysis#software-design#digital-mars#frama-c#c23

Комментарии (82)

  • Участники спорят, что считать «контрактом»: от assert до полноценных спецификаций, проверяемых компилятором.
  • Проблема С/С++: нет единого стандарта, каждый реализует по-своему (Digital Mars — с 90-х, Frama-C, C23 unreachable()).
  • Часть сообщества считает контракты костылем для слабой типизации: «если типы не выражают инварианты, добавь ещё один слой».
  • Критика С23: макрос contract_assume вызывает UB через unreachable(), что делает поведение непредсказуемым и оптимизацию агрессивной.
  • Альтернативы: переходить на Ada/SPARK, Rust, OCaml — там контракты либо встроены, либо доказываются статически.

How is Ultrassembler so fast? (jghuff.com)

Ultrassembler — библиотека RISC-V-ассемблера, встроенная в проект Chata.
В отличие от as и llvm-mc, она вызывается прямо из C++, без system() и временных файлов, что критично для встроенных систем.

Скорость

Тест на 16 тыс. инструкций:

  • Ultrassembler ≈ 10× быстрее as, 20× быстрее llvm-mc.
  • 1 RISC-V инструкция ≈ 1000 x86-инструкций (у конкурентов 10–20 тыс.).
    Код на чистом C++; можно добавить ассемблерные вставки.

Ключевые оптимизации

Исключения

GCC-реализация «zero-overhead»: штрафа нет, пока исключений нет.
Ошибки встречаются редко и видны человеку, поэтому даже 1 с на обработку незаметна.
std::expected дал −10 %, так как нормальный путь стал дороже.

Быстрые структуры

2000+ RISC-V-инструкций требуют мгновенного поиска.
Вместо std::unordered_map используется perfect-hash таблица от gperf, генерирующая O(1) без коллизий.
Размер таблицы компактен, кэш-эффективен.

Парсинг

  • Регистры идентифицируются по первым 2–3 символам через switch.
  • Нет std::string, только std::string_view и статические буферы.
  • Лексемы разбираются за один проход без регулярных выражений.

Кодогенерация

  • Шаблоны на этапе компиляции формируют битовые маски инструкций.
  • Варианты одной инструкции разворачиваются в constexpr-таблицы, что убирает ветвления в рантайме.

Память

  • Все выделения через стековые std::array/std::string_view.
  • Нет new/malloc, следовательно, нет аллокационных штрафов и кэш-промахов.

Платформенные трюки

  • [[likely]]/[[unlikely]] для подсказок ветвления.
  • __builtin_expect там, где компилятор не догадывается.
  • LTO + PGO дают ещё 5–7 %.

Итог

Ultrassembler показывает, что «низкоуровневый» C++ без искусственных ограничений может обгонять даже оптимизированные GNU-утилиты.

by netr0ute • 31 августа 2025 г. в 17:42 • 98 points

ОригиналHN

#c++#risc-v#assembler#gcc#llvm#performance-optimization#hash-tables#compiler-optimization#embedded-systems

Комментарии (34)

  • В обсуждении разобрали миф о «системном вызове при каждом росте контейнера» — реальные аллокаторы переиспользуют память и делают syscall лишь при нехватке.
  • Участники напомнили, что исключения в C++ не «zero-overhead»; есть компромисс между временем и памятью, и g++ выбирает экономию места.
  • Автор статьи подтвердил: пробовал хеширование, но дерево разбора оказалось быстрее; flex/bison тут не при чём, скорее gperf.
  • Некоторые посоветовали LLVM C++ API, memory-mapped I/O и std::pmr для ускорения и упрощения кода.
  • Большинство сходится: современные ассемблеры и так быстрые, задача скорее академическая, но как «посмотреть, насколько можно ускорить» — интересна.

10-20x Faster LLVM -O0 Back-End (2020) (discourse.llvm.org)

TPDE-LLVM — новый бэкенд LLVM-O0, который в 10–20 раз быстрее стандартного, при сопоставимой скорости выполнения и росте кода на 10–30 %. Работает с IR Clang-O0/O1, цели x86-64 и AArch64.
Данные SPEC CPU 2017 (x86-64, ускорение компиляции и размер кода относительно LLVM 19 -O0):

бенчмарк O0 IR O1 IR
perl 11.4× / 1.27× 15.1× / 0.97×
gcc 12.5× / 1.32× 17.6× / 1.01×
omnetpp 21.5× / 1.24× 26.5× / 1.03×
геом.ср. 13.3× / 1.27× 17.6× / 0.97×

Как работает: три прохода — очистка IR, анализ (циклы + liveness), единый codegen (lowering, регистры, кодирование).
Поддержка: как библиотека, llc-подобный инструмент, патч для Clang. DWARF и улучшенный рег-аллокатор в планах.
Ограничения: не все IR-конструкции, векторы, TLS-глобалы, i260 и т.д.

Что ускорило бы LLVM ещё сильнее:

  • убрать ConstantExpr внутри функций;
  • запретить гигантские структуры/массивы как значения;
  • упростить доступ к TLS и произвольную битовую арифметику.

by signa11 • 31 августа 2025 г. в 15:50 • 100 points

ОригиналHN

#llvm#clang#compiler-optimization#x86-64#aarch64#spec-cpu-2017#ir

Комментарии (6)

  • Пользователи обсудили, что Gentoo всё ещё используют с флагом -O8 для максимальной производительности.
  • Кто-то спросил, нужно ли добавить пометку «(2020)» к цитируемому тексту.
  • Упомянули, что «все» якобы перешли на Arch, где компилятор якобы умеет -O11.
  • Уточнили: пост 2025 года, но он цитирует запись 2020-го; попросили модератора исправить.