# Perry
**Write TypeScript. Ship native. Everywhere.**
Perry compiles the TypeScript you already write into real machine-code executables — for macOS, Windows, Linux, iOS, Android, watchOS, and TV. No Node.js to install. No Electron to bundle. No runtime at all. Just a binary. (The same codebase can also target the web, emitted as JavaScript or WebAssembly.)
[](https://github.com/PerryTS/perry/releases/latest)
[](https://discord.gg/chEmpGdTtZ)
[Website](https://perryts.com) · [Documentation](https://perryts.github.io/perry/) · [Showcase](https://perryts.com/showcase) · [Examples](https://github.com/PerryTS/perry-examples)
```bash
perry compile src/main.ts -o myapp
./myapp # a standalone native binary — ~330 KB for hello world
```
## The language you know. The deployment you wish it had.
Millions of developers write TypeScript every day — but shipping it has always meant shipping a JavaScript engine: a Node install on every server, ~100 MB of embedded runtime per CLI, or a whole browser engine per desktop app. Perry removes the engine. SWC parses your code, LLVM compiles it to machine code, and you get what systems languages get: instant cold starts, tiny self-contained binaries, real threads — without leaving TypeScript.
| | **Perry** | Node.js | Bun | Electron |
|---|---|---|---|---|
| **What you ship** | One native binary, from ~330 KB | Your code + a Node install | One binary embedding the JS engine | App bundle with a browser engine |
| **Execution** | Ahead-of-time machine code | JIT | JIT | JIT |
| **Cold start** | Instant — no engine to boot, no warmup | Engine boot + warmup | Engine boot + warmup | Browser boot |
| **Native UI (no WebView)** | ✅ AppKit, UIKit, Android Views, Win32, GTK4 | — | — | Chromium |
| **iOS · Android · watchOS · TV** | ✅ from the same codebase | — | — | — |
| **Multicore** | Real OS threads, data-race-safe at compile time | worker_threads | workers | processes |
Table describes Perry's native targets. `--target web` / `--target wasm` emit JavaScript / WebAssembly that runs in the browser rather than as a native binary.
## Performance
Ahead-of-time machine code means no engine boot and no JIT warmup — and on measured workloads, real multiples over the JS runtimes. Highlights from our open benchmark harnesses (Apple M1 Max, medians of repeated runs):
| Workload | **Perry** | Node.js | Bun | Rust |
|---|---:|---:|---:|---:|
| Image convolution (4K, 5×5 Gaussian) | **354 ms** | 1,207 ms — *3.4× slower* | 915 ms — *2.6× slower* | 392 ms |
| Fibonacci (recursive calls) | **309 ms** | 987 ms — *3.2× slower* | 518 ms — *1.7× slower* | 316 ms |
| JSON pipeline (100 records) | **39 ms** | 144 ms — *3.7× slower* | 51 ms — *1.3× slower* | 34 ms |
| JSON pipeline (500k records, 108 MB) | **1,649 ms** | 1,010 ms — *1.6× faster* | 647 ms — *2.5× faster* | 604 ms |
| Object allocation (1M objects) | **2 ms** | 8 ms — *4× slower* | 6 ms — *3× slower* | <1 ms |
| Array write (10M elements) | **3 ms** | 9 ms — *3× slower* | 6 ms — *2× slower* | 7 ms |
| Peak memory (JSON pipeline) | **3.5 MB** | 36 MB — *10× more* | 11 MB — *3× more* | 1.2 MB |
Look at the Rust column again: on convolution, fibonacci, and the array-write loop, TypeScript compiled with Perry **runs even with — or ahead of — Rust**. And Electron isn't in the table because it doesn't compete here: it ships a whole browser engine per app, where a comparable Perry app is a single-digit-MB native binary.
Sources: convolution & JSON from the [systems-language report](https://github.com/PerryTS/perry/blob/7beb3a50ca/benchmarks/honest_bench/REPORT.md)
— pinned to `7beb3a50ca`, the last revision whose artifact contains these values; the copy at HEAD was regenerated in #7641 on a host
where the harness clock was invalid and now reads 0.0 ms in every timing cell (see this PR). Re-pin to `main` once it is regenerated.
Fibonacci, object allocation & array write from the [polyglot sweep](benchmarks/polyglot/RESULTS.md) (Perry default mode, no fast-math).
We publish *everything*, including the workloads where V8's JIT still beats us — no cherry-picked table can survive an open harness. Run it yourself: `./benchmarks/run_public_baseline.sh` ([methodology](benchmarks/README.md)).
The full published suite, generated from the artifact — including the rows we lose
Generated from [`benchmarks/results/public-node-bun-v1.json`](benchmarks/results/public-node-bun-v1.json) at Perry commit `827a92bad5a5`.
Lower wall-clock median is better; every row includes complete raw samples and passed correctness checks.
| Benchmark | Perry | Node.js | Bun | Result | What it tests |
|---|---:|---:|---:|---|---|
| factorial | 59 ms | 95 ms | 61 ms | win vs both | Modular accumulation |
| method_calls | 6 ms | 9 ms | 4 ms | mixed | Class method dispatch |
| closure | 29 ms | 30 ms | 29 ms | mixed | Closure creation and invocation |
| binary_trees | 6 ms | 5 ms | 9 ms | mixed | Tree allocation and traversal |
| string_concat | 5 ms | 37 ms | 12 ms | win vs both | String append loop |
| prime_sieve | 4 ms | 4 ms | 5 ms | mixed | Sieve of Eratosthenes |
| mandelbrot | 15 ms | 17 ms | 16 ms | win vs both | Complex-number iteration |
| matrix_multiply | 22 ms | 24 ms | 22 ms | mixed | Matrix multiplication |
| json_roundtrip | 186 ms | 407 ms | 189 ms | win vs both | Parse and stringify ~1 MB JSON |
💎 Skelpo — Premium Sponsor
Want to support Perry and see your logo here? Get in touch via [perryts.com](https://perryts.com). ## License MIT