ghc-fastboot¶
Zero-cost serialization for GHC Haskell. Freeze any closure graph — constructors, thunks, functions, partial applications — into a snapshot and thaw it back in microseconds.
What it does¶
main = do
let config = frozen ".cache/config" loadConfig
index = frozen ".cache/index" buildIndex
grammar = frozen ".cache/grammar" parseGrammar
runApp config index grammar
First run: evaluates each expression, walks the closure graph, serializes to disk.
Every subsequent run: mmap + mremap the data directly into the GHC heap. No parsing, no deserialization, no allocation. The closures are just there.
Performance¶
1M-entry Vector Text benchmark (91MB closure data):
| Approach | Startup time | Speedup |
|---|---|---|
| Build from scratch | 618ms | 1x |
| Thaw from file (mmap) | 2.6ms | 238x |
| Thaw from ELF section (mremap) | 2.6ms | 238x |
Data pages are demand-paged: only pages you actually access incur a fault (~40ns each). A CLI tool that touches 100 entries out of 1M pays for 100 entries, not 1M.
How it differs from GHC Compact Regions¶
| Compact Regions | ghc-fastboot | |
|---|---|---|
| Thunks | No (NF only) | Yes |
| Functions / PAPs | No | Yes |
| Closures over free vars | No | Yes |
| Cross-binary migration | No | Yes (symbol table + dlsym) |
| Layout | Compacted, contiguous | Compacted, contiguous |
| GC integration | Built-in | Manual bdescr + StablePtr |
| Requires GHC patch | No | No |
The closure walker handles all GHC closure types via info table traversal — the same mechanism the GC uses.
Haskell API¶
-- Freeze/thaw without binary compatibility checks.
-- First run: evaluates action, serializes result to path.
-- Subsequent runs: thaws from snapshot (or ELF section if embedded).
frozen :: FilePath -> IO a -> a
-- Same as frozen (no binary hash verification yet).
unsafeFrozen :: FilePath -> IO a -> a
frozen uses unsafePerformIO. The snapshot path is the fallback — if the binary has an embedded snapshot (ELF section), it's used first with zero file I/O.
Building¶
# Default build (library + benchmarks)
nix build
# Embedded binary (three-phase: build → snapshot → objcopy)
nix build .#bench-embedded
# Development
nix develop
cabal build
Project Structure¶
ghc-fastboot/
├── lib/FastBoot.hs # Haskell API: frozen, unsafeFrozen
├── cbits/
│ ├── fastboot.h # Snapshot format structs, constants
│ ├── freeze.c # Closure graph walk + serialize
│ ├── thaw.c # mmap/mremap restore + GC setup
│ ├── closure_walk.h # Info table-driven closure walker
│ ├── relocate.c # ASLR relocation (v1)
│ ├── embed.c # Binary embedding
│ ├── embed_section.S # ELF section placeholder
│ └── fastboot.ld # Linker script (section after .bss)
├── bench/
│ ├── mini-fzf-frozen/ # 1M-entry Vector Text benchmark
│ ├── mini-fzf/ # Unfrozen baseline
│ └── minimal/ # RTS overhead baseline
├── docs/ # Documentation (this site)
└── flake.nix # Nix build with three-phase pipeline