Компиляторы

DSL компиляторы

PostgreSQL выполнял запрос за 185 секунд. DuckDB тот же запрос за 3 секунды. Разница - компиляция SQL в нативный код через LLVM вместо интерпретации плана. В играх - shader compilation stutter из-за компиляции GLSL в GPU ISA при первом рендере. В DevOps - Dhall компилирует типизированные конфигурации в JSON предотвращая ошибки до деплоя. DSL компиляторы - это специализированные решения которые меняют что вообще возможно в своём домене.

  • **DuckDB** (in-process OLAP): компилирует SQL expressions через LLVM и генерирует SIMD-векторизованный код; 60x быстрее PostgreSQL для аналитических запросов на ноутбуке
  • **Apple Metal**: шейдеры компилируются в AIR во время сборки Xcode проекта - не в рантайме. Это устраняет shader compilation stutter который есть в Vulkan/OpenGL играх
  • **ClickHouse GROUP BY JIT**: первый запрос компилирует агрегационный код через LLVM; последующие запросы с тем же паттерном используют скомпилированный код с 5-10x speedup

Query Engines и compilation

Традиционные query engines (Volcano/Iterator model) интерпретируют план запроса: каждый оператор (Scan, Join, Aggregate) реализует `next()` метод, данные текут через цепочку операторов. Overhead на каждый кортеж: виртуальные вызовы, branch mispredictions, cache misses. Компилирующие движки (Hyper, DuckDB, LLVM-based) генерируют нативный код для всего pipeline запроса.

DuckDB использует Push-based execution с компиляцией через вставку кода операторов в общий pipeline. Velox (Meta, 2022) - векторизованный execution engine используемый в Presto и Spark, компилирует выражения через LLVM JIT. ClickHouse компилирует GROUP BY агрегации через LLVM в рантайме: первый запрос медленнее, последующие до 10x быстрее.

Почему компилирующий query engine быстрее Volcano-model?

SQL Компиляция: от AST до нативного кода

SQL компиляция: SQL строка -> лексер/парсер -> AST -> semantic analysis (типы, таблицы) -> logical plan -> optimizer (pushdown, join ordering) -> physical plan -> code generation (LLVM IR или code templates). Optimizer - самая сложная часть: поиск оптимального plana NP-hard для N join'ов.

PostgreSQL 11+ включает JIT компиляцию через LLVM для тяжёлых запросов: expressions, aggregation functions, tuple deforming. Включается автоматически при cost > jit_above_cost (100000). Apache Arrow Flight SQL - протокол для передачи скомпилированных query plans между движками. Calcite (Apache) - фреймворк для написания SQL оптимизаторов используемый в Hive, Flink, Drill.

Почему оптимизация JOIN ordering в SQL оптимизаторе является NP-hard задачей?

Shader Compilers

Shader compiler транслирует GLSL/HLSL/Metal Shading Language в GPU ISA (AMD GCN, NVIDIA SASS, Intel EU ISA). Pipeline: source -> frontend (Clang для Metal/HLSL) -> SPIR-V (стандартный промежуточный формат) -> vendor backend -> GPU binary. Шейдеры компилируются при первом использовании что вызывает stuttering.

Shader compilation stutter - известная проблема в играх: Cyberpunk 2077 при релизе компилировал шейдеры во время gameplay. Решения: Pipeline State Object cache (DirectX 12), Metal shader precompilation (Apple), Vulkan pipeline cache. Apple Metal через Xcode компилирует Metal шейдеры в AIR (Apple Intermediate Representation) при сборке приложения, избегая runtime компиляцию.

Зачем нужен промежуточный формат SPIR-V между GLSL и GPU ISA?

Конфигурационные языки и компиляция

Конфигурационные DSL (Dhall, CUE, Jsonnet, Nix) - языки с системами типов, компиляцией в JSON/YAML и guarantees корректности. Dhall полностью детерминирован и total: нет IO, нет бесконечных циклов, всегда завершается. Это делает возможным статическую верификацию конфигурации перед деплоем.

Dhall используется в Tweag (функциональное консалтинговое агентство) для генерации Kubernetes YAML: типовая система Dhall предотвращает ошибки в конфигурации до деплоя. Pulumi (Infrastructure as Code) использует TypeScript/Python как DSL с полноценным type checking. HashiCorp Sentinel - policy language компилируемый в bytecode для Terraform/Vault access policies.

DSL компиляторы всегда проще компиляторов общего назначения

DSL компиляторы часто содержат domain-специфическую сложность: SQL оптимизатор (NP-hard join ordering), shader compiler (vendor GPU ISA), конфигурационный язык (totality checking) - каждый требует глубокой domain expertise

SQL оптимизатор в PostgreSQL - ~100,000 строк кода. GLSL компилятор Mesa3D - ~200,000 строк. Nix evaluator сложнее многих general-purpose интерпретаторов. Domain constraints создают специфическую сложность которой нет в компиляторах общего назначения

Чем Dhall отличается от JSON/YAML как конфигурационный язык?

Итоги

  • Query engines: компилированный pipeline (DuckDB, Hyper) устраняет virtual dispatch и даёт SIMD векторизацию - 10-100x быстрее Volcano model для аналитических запросов
  • Shader compilers: GLSL/HLSL -> SPIR-V (vendor-neutral IR) -> GPU ISA; shader stutter из-за runtime компиляции решается через pipeline cache и precompilation
  • Config DSL (Dhall, CUE): типовая система + totality гарантия позволяют верифицировать конфигурацию статически до деплоя

Связанные темы

DSL компиляторы применяют компиляторные техники в специализированных доменах:

  • MLIR — MLIR используется в ML компиляторах как domain-specific IR; подход аналогичен SPIR-V для GPU
  • JIT-компиляция основы — ClickHouse и DuckDB применяют JIT компиляцию SQL во время выполнения запроса
  • LLVM инфраструктура — PostgreSQL JIT, DuckDB, ClickHouse используют LLVM как backend для SQL компиляции

Вопросы для размышления

  • DuckDB компилирует SQL через LLVM. При каких размерах данных overhead на компиляцию (100ms) перестаёт окупаться выигрышем от нативного кода?
  • Shader compilation stutter можно устранить precompilation. Но шейдеры часто параметризованы (материалы, освещение). Как игровые движки справляются с комбинаторным взрывом вариантов шейдеров?
  • Dhall гарантирует завершение (totality). Какие вычисления это делает невозможными? Что не выразимо в Dhall что возможно в Turing-complete конфигурации?

Связанные уроки

  • fl-01-intro
DSL компиляторы

0

1

Войти