- Perry là compiler TypeScript viết bằng Rust, parse bằng SWC, sinh mã native qua LLVM.
- Một file .ts → một executable 2–5MB chạy trên 10 platform (macOS, iOS, Android, Windows, Linux, watchOS, tvOS, Web, WASM) với widget native thật, không WebView, không Electron.
TL;DR
Perry (v0.5.17, MIT) là một compiler TypeScript viết bằng Rust: SWC parse, LLVM sinh mã, output là một binary native duy nhất. Không Node, không V8, không Electron mặc định. Hello world ~330KB, app điển hình 2–5MB. Startup ~1ms. Trên benchmark macOS ARM64, Perry nhanh hơn Node.js v25 tới 24.6× (factorial), 38× (closure), và bằng hoặc thắng Rust/C++ trên 7/8 bài polyglot. Một codebase compile sang 10 target — macOS (AppKit), iOS (UIKit), Android (Views), Windows (Win32), Linux (GTK4), watchOS, tvOS, Web, WebAssembly — với widget native thật.
What's new
Phiên bản 0.5.x đánh dấu Perry chuyển hẳn code-gen backend từ Cranelift sang LLVM. Đổi lại ~25ms compile time mỗi file, runtime nhanh hơn tới 24×. Bulk thời gian compile vốn nằm ở SWC parsing + HIR lowering + linking, nên tổng compile chỉ tăng 8–19% — một trade rất đáng.
Perry không cố gắng chạy mọi npm package qua V8. Thay vào đó nó reimplement native bằng Rust các package phổ biến nhất: fastify, axios, ws, mysql2, pg, ioredis, bcrypt, argon2, jsonwebtoken, dotenv, uuid, nodemailer, zlib, node-cron. Pure-JS packages còn lại có thể bật V8 runtime opt-in qua --enable-js-runtime (cộng ~15MB).
Why it matters
Cross-platform native từ TypeScript là vùng đất React Native, Flutter, KMP đã cày — nhưng tất cả đều kéo theo một runtime nặng (Hermes/V8 + Bridge, Dart VM, Kotlin runtime). Perry là framework đầu tiên AOT compile TS thẳng ra machine code với widget native thật, runtime overhead bằng không.
Đây không phải chỉ trick benchmark. Một MongoDB GUI built bằng Perry (Mango) ship dưới ~7MB binary, dùng <100MB RAM, cold start sub-second. So với Electron: thường ngốn 80–150MB cài đặt, 200MB+ RAM ở idle. Đối với CLI tool và lambda function — startup ~1ms cộng zero JIT warmup là một game changer.
Technical facts
Bảng số liệu vs Node.js v25 và Bun 1.3 (best of 3, macOS ARM64):
| Metric | Perry | Node.js | Bun |
|---|---|---|---|
| Binary size | 2–5 MB | ~80 MB | ~90 MB |
| Startup time | ~1 ms | ~30 ms | ~10 ms |
| Hello world binary | ~330 KB | n/a | n/a |
| factorial | 24 ms | 592 ms (24.6×) | 99 ms |
| closure (10M calls) | 8 ms | 305 ms (38×) | 50 ms |
| method calls (10M) | 2 ms | 11 ms (5.5×) | 7 ms |
| fibonacci(40) | 310 ms | 991 ms (3.2×) | 514 ms |
| array_read (10M) | 4 ms | 14 ms (3.5×) | 18 ms |
| matrix_multiply 256² | 22 ms | 34 ms (1.5×) | 34 ms |
Điểm thú vị: Perry beat hoặc tie Rust và C++ trên 7 / 8 polyglot benchmarks. Ví dụ loop_overhead Perry 12ms vs Rust/C++ 96ms; math_intensive 14ms vs Rust 48ms. Lợi thế đến từ domain-specific optimizations cho TS number type: reassoc fast-math flags, integer-modulo fast path (fptosi → srem → sitofp thay fmod), i64 specialization cho recursive numeric functions, scalar replacement biến object fields thành CPU registers.
TypeScript coverage: classes (private #, inheritance, static, getters/setters), generics (monomorphized compile-time như Rust), async/await, generators, BigInt 256-bit, RegExp, Maps/Sets, decorators, ES modules, destructuring, spread. Stdlib có fs, path, process, crypto, os, Buffer, child_process, worker_threads.
Comparison
| Framework | Lang | AOT Native | Native widgets | Runtime overhead |
|---|---|---|---|---|
| Perry | TypeScript | ✅ | ✅ AppKit/UIKit/GTK4/Win32 | None |
| React Native | JS/TS | ❌ JIT | ✅ | Hermes/V8 + Bridge |
| Flutter | Dart | ✅ | Custom (Skia) | Dart VM |
| KMP + Compose | Kotlin | Partial | ✅ | Kotlin runtime |
| NativeScript | JS/TS | ❌ | ✅ | V8 / JSC |
| Ionic / Tauri WebView | JS/TS | ❌ | ❌ | WebView |
Use cases
- Desktop & mobile GUI: Mango (MongoDB GUI ~7MB), Hone (AI code editor với terminal/Git/LSP), Pry (JSON viewer trên App Store + Play Store), dB Meter (60fps sound level).
- Game engines: Bloom Engine — 2D/3D rendering, skeletal animation, spatial audio, Metal/DirectX 12/Vulkan/OpenGL.
- Backend APIs: Fastify/Express/Hono/NestJS — single binary, không
node_modulesở production. Compile vào ~48MB nếu nhúng full stdlib. - CLI tools & lambdas: 1ms cold start + zero GC pause = lý tưởng cho short-lived processes.
- Widgets & wearables: WidgetKit (iOS), watchOS, Wear OS, Android — viết một lần TS, deploy multi-platform.
Limitations & pricing
Perry không phải drop-in cho mọi codebase Node hiện có. Vài cái cần biết:
- Single-threaded by default. Concurrent server requests serialize, có thể trả 503 dưới load. Cần dùng
perry/threadvớiparallelMap/spawnđể khai thác multi-core. - No runtime type checking. Types bị erase hoàn toàn để optimize direct field offsets — bad input có thể crash thay vì throw
TypeError. Phải validate ở boundary bằngtypeof/instanceof. - GC mặc định không reclaim trong benchmark mode — long-running server cần engage mark-sweep GC; CLI/lambda thì không cần.
- NPM gap. Pure-JS package dùng native addons hoặc Node API chưa support phải bật V8 runtime (+15MB binary).
- Windows code signing qua Perry Publish vẫn coming soon.
License: MIT, open source. Pricing: compiler hoàn toàn free. Phần thương mại là Perry Publish — cloud cross-compile + code-sign + đẩy thẳng lên App Store/Play Store. Free cho OSS project, paid plan cho private team. Cài: brew tap PerryTS/perry && brew install perry (macOS), winget (Windows), APT (Debian/Ubuntu), hoặc build from source.
What's next
Repo hoạt động cực kỳ active — commit cách đây vài giờ (fix typed-array pointer bitcast), gói @perryts/threads tương thích Node worker_threads ship 6 giờ trước, perry/widget full hỗ trợ iOS + Android + watchOS + Wear OS tháng trước. Tài liệu PERF_ROADMAP.md liệt kê "three optimizations to close the Zig gap" — Perry đang bám sát Zig về single-thread perf.
Câu hỏi lớn cho cộng đồng: liệu Perry có lan ra ngoài niche các tool dev nhỏ-gọn (CLI, JSON viewer, Mongo GUI) sang production-scale backend hay app store consumer apps? Với việc Mango và Pry đã lên store, và Hone đang vận hành như editor có LSP, đáp án có vẻ tích cực. Worth thử ngay nếu bạn đang đau đầu vì Electron 200MB hoặc Node cold-start 30ms.
Nguồn: PerryTS/perry, perryts.com, docs.perryts.com, demo benchmark.
