Luna Benchmark Report

Comparison benchmark results: Luna vs React vs Preact.

TL;DR - Luna's Strengths

MetricLunaNote
Bundle Size9.4 KB (gzip)1/6 of React
SSR Performance12,800 pages/sec1000-item list
Signal Update11M ops/secFine-Grained Reactivity
Partial Update4.5M ops/secDirect DOM update

Bundle Size Comparison

LibraryMinifiedGzipvs React
React 19 + ReactDOM193 KB60 KB-
Luna33 KB9.4 KB6x smaller
Preact 10 + hooks13 KB5.4 KB15x smaller

Luna is 1/6 the size of React. Larger than Preact, but includes Signal, SSR, and Island Architecture as a full-stack framework.

Runtime Performance

Benchmark results in jsdom environment (vitest bench).

Initial Mount (2,500 cells)

Libraryops/secvs Preact
Preact9811x
React1238x slower
Luna6714.6x slower

Reactive State Mount (2,500 cells)

Libraryops/secvs Preact
Preact611x
React421.4x slower
Luna421.5x slower

State Update (2,500 cells)

Libraryops/secvs Preact
Preact12,5231x
React119105x slower
Luna111113x slower

Note: Preact's extremely fast update may be due to state change batching.

Large Grid (5,000 cells)

Libraryops/secvs Preact
Preact3871x
React537.3x slower
Luna2913.3x slower

List Operations (Add 100 items)

Libraryops/secvs Preact
Preact2,8761x
React6544x slower
Luna7240x slower

Analysis

Current Status

Luna is currently slower than React/Preact in raw speed. This is due to:

  1. MoonBit → JS compilation: Generated JS code has room for optimization compared to hand-written code

  2. Fine-Grained Reactivity overhead: Dependency tracking cost per element

  3. Early development stage: Optimization work is still in progress

Luna's Value Proposition

Speed isn't everything. Luna provides these values:

FeatureLunaReactPreact
Island Architecture✅ Built-in
Fine-Grained Reactivity❌ (VDOM)❌ (VDOM)
SSR✅ NativeRequires Next.js etc.✅ preact-render-to-string
Hydration Strategies✅ load/idle/visible/media
Type Safety✅ MoonBitTypeScriptTypeScript
Multi-target✅ js/native/wasmJS onlyJS only

Future Optimization Opportunities

  1. wasm-gc target: MoonBit can compile to wasm-gc, potentially faster than JS in the future

  2. Compiler optimization: Automatic speedup through MoonBit compiler improvements

  3. DOM operation optimization: Current implementation has room for improvement

Benchmark Environment

  • Node.js v24 + jsdom

  • Vitest 4.0.15

  • macOS Darwin 24.5.0

Running Benchmarks

cd luna.mbt
npx vitest bench js/luna/benches/grid.bench.ts --run

Luna's Strengths - MoonBit Benchmarks

Internal MoonBit benchmark results for Luna. These demonstrate Luna's architectural strengths.

SSR (Server-Side Rendering)

TestTimeops/sec
Simple element0.13 µs7.7M
10 item list0.83 µs1.2M
100 item list8.12 µs123K
1000 item list78 µs12.8K
10 card page5.95 µs168K
50 card page28.5 µs35K
100 card page58.4 µs17K

SSR performance is extremely fast - Can generate a 1000-element list in 78µs.

Signal (Fine-Grained Reactivity)

OperationTimeops/sec
Signal::new~0.36 µs/100280K
Signal::get0.28 µs/10003.6M
Signal::set0.09 µs11M
Memo cached read0.28 µs/10003.6M
Memo recompute0.63 µs1.6M
Effect rerun~1 µs1M
Batch 100 updates5 µs200K

Signal updates at 11M ops/sec - Orders of magnitude faster than React's setState.

DOM Updates (Fine-Grained)

OperationTimeops/sec
Text update0.22 µs4.5M
Attr update0.39 µs2.6M
Show toggle2.56 µs390K
Deep update (5 levels)0.37 µs2.7M

Partial updates at 4.5M ops/sec - Direct DOM updates without VDOM diffing.

Why Luna is Slower in VDOM Benchmarks

Luna is slower than Preact in grid benchmarks (updating all 2,500 cells), because:

  1. Full element updates are not Luna's target use case

    • Fine-Grained Reactivity assumes "update only parts"

    • Updating all 2,500 cells every time suits VDOM

  2. Luna's design philosophy

    • Only changed Signals update the DOM

    • 1 cell update = 0.22µs (no VDOM diff needed)

  3. In real apps, Luna excels when

    • Most UIs involve partial updates

    • Island Architecture distributes initialization cost

Conclusion

When Luna is a Good Fit

  • ✅ Need SSR + selective hydration

  • ✅ Want Island Architecture for partial hydration

  • Frequent partial updates (reactive dashboards, etc.)

  • Small bundle size matters (1/6 of React)

  • ✅ Want type-safe UI with MoonBit

  • ✅ Looking ahead to wasm-gc support

When Luna is Not a Good Fit

  • Mass element updates (game frame updates, etc.)

  • ❌ Need React/Preact ecosystem (existing libraries)

Comparison Summary

AspectLunaPreactReact
Bundle Size⭐⭐⭐ 9KB⭐⭐⭐⭐ 5KB⭐ 60KB
Full Update⭐⭐⭐⭐⭐⭐
Partial Update⭐⭐⭐⭐⭐⭐⭐⭐
SSR⭐⭐⭐⭐⭐⭐⭐⭐
Island Architecture⭐⭐⭐⭐ Built-in