Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Perry is the better fit for most teams that want a complete native application platform: it compiles TypeScript and JavaScript to standalone machine-code binaries and documents desktop, Apple, Android, web/WASM, native UI, threads, and Node-compatible APIs. scriptc is the more deliberately bounded option: its documented comparison centers on a typed compiler pipeline with explicit static, dynamic, and rejected-code boundaries. That makes it attractive when you need an inspectable compilation contract rather than a broad application framework.
There is no evidence of a universal speed winner. Perry’s published benchmarks show large gains on some CPU-heavy workloads and losses on a JSON pipeline, while no directly comparable scriptc benchmark set is established. The reliable choice comes from your target platforms, API dependencies, tolerance for a JavaScript fallback, and measurements on your own code.
As an Amazon Associate I earn from qualifying purchases.
What are Perry and scriptc designed to do?
Perry and scriptc both aim to turn TypeScript into native machine code, but they frame the problem differently. Perry presents itself as an end-to-end application platform. Its project slogan is “Write TypeScript. Ship native. Everywhere.” The compiler is implemented in Rust, uses SWC and LLVM, and emits standalone binaries for a range of targets.
scriptc is described in an independent comparison as “TS → IR → LLVM → native, no JS engine.” Its emphasis is the compilation contract: TypeScript is parsed and type-checked, lowered into a typed intermediate representation, converted to LLVM IR, passed through clang, and linked into a native executable. The comparison explicitly distinguishes code that can be compiled statically, code that requires a dynamic runtime, and code that is rejected.
#1 Best Overall
Those positions lead to different buying decisions. Perry asks whether your application can use its supported TypeScript/JavaScript subset and runtime implementations across several platforms. scriptc asks whether each part of your program fits a clearly defined static or dynamic boundary. Neither description establishes that one project accepts every TypeScript feature or every npm package.
How do their compilation pipelines differ?
Perry’s pipeline is intended to hide most compiler mechanics from application developers. You write TypeScript or JavaScript, select a target, and receive a native artifact. Features that need compatibility behavior can use runtime support rather than being lowered entirely into specialized machine code. The exact path depends on the API and target, so a successful build does not by itself prove that every code path is engine-free.
Free tools Windows power users keep installed
One-click scans. No signup required.
scriptc exposes more of the boundary. Its static path lowers typed code through an intermediate representation and LLVM. A --dynamic mode can embed quickjs-ng, allowing JavaScript that cannot be represented by the static compiler to execute inside the resulting program. This creates a deliberate hybrid rather than an all-or-nothing promise.
- Parse and type-check: both approaches start from TypeScript syntax and types, but scriptc’s published description makes this front end an explicit stage.
- Lower to an intermediate form: scriptc uses a typed IR before generating LLVM IR. Perry also relies on LLVM in its native toolchain, while presenting the intermediate stages as an implementation detail to application authors.
- Generate and link native code: LLVM IR is compiled and linked into an executable. Static code does not need a JavaScript engine at runtime.
- Handle unsupported behavior: scriptc can reject code or place it in a dynamic island. Perry supplies compatibility implementations and optional runtime behavior, so the project’s compatibility documentation for your target must be checked feature by feature.
The practical distinction is predictability versus breadth. A strict boundary can make failures easier to reason about before deployment; a broad platform can reduce the amount of platform-specific code you must write.
Which platforms and application features does each compiler support?
Perry has the broader published target story. It documents desktop systems, Apple platforms, Android, web/WASM output, and additional targets, along with native UI, real operating-system threads, Node-compatible APIs, and integrations with packages. scriptc’s comparison establishes its native executable pipeline but does not provide a comparable UI framework or a complete platform matrix.
| Capability | Perry | scriptc |
|---|---|---|
| Desktop native binaries | Documented as a core target | Native executable output is described; supported operating systems are not stated in the comparison |
| Apple and Android targets | Documented targets | Not stated |
| Web or WebAssembly | Documented target family | Not stated |
| Native user interfaces | Documented | No comparable UI framework is documented |
| Operating-system threads | Documented real OS threads | Not stated |
| Node-compatible APIs | Documented, with feature-specific coverage results | Not established by the available comparison |
| JavaScript fallback | Optional runtime behavior is documented for compatibility paths | --dynamic can embed quickjs-ng |
For a desktop or mobile product, this difference is significant. Perry is trying to supply the UI, packaging, and platform layers that turn a compiler into an application stack. With scriptc, you should assume that those layers will come from your own code or other libraries until its current first-party documentation says otherwise.
How does scriptc’s static, dynamic, and rejected model work?
scriptc’s most distinctive idea is that not all JavaScript-like behavior is treated the same way. Statically compilable code can be lowered to native instructions. Code that depends on runtime features can be isolated in a dynamic region and executed by quickjs-ng. Code outside either boundary is rejected at compile time instead of silently receiving an unexpected implementation.
Rank #2
- Perfect for front-end developers, full-stack engineers, and software architects who build large-scale web applications and want to showcase their passion for strictly typed development and modern coding practices.
- Great gift for programmers, computer science students, and tech professionals who love TypeScript syntax, static type checking, and building robust web applications for birthdays, holidays, or developer meetups.
Static code
Static compilation is the path for code whose types, operations, and dependencies can be represented by the compiler’s typed IR and LLVM backend. It avoids a JavaScript engine in the final execution path and is the route to the most predictable startup and memory behavior.
Dynamic islands
The dynamic mode embeds quickjs-ng so that selected JavaScript can run at runtime. This is useful for reflective code, unusual language features, or dependencies that have not yet been lowered statically. The trade-off is an included engine, additional memory, and behavior that must be tested separately from the native portion.
Rejected code
Rejection is a contract, not merely a build failure. It tells you that a construct cannot be represented by the available static or dynamic path. Teams can then replace the dependency, isolate it behind a dynamic boundary, or choose another compiler instead of discovering the limitation after release.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPerry also has compatibility-oriented runtime behavior, but its public positioning is less about exposing a three-way classification and more about making a broad TypeScript/JavaScript application stack work across targets. Read the target-specific compatibility notes before assuming that a Perry build is entirely engine-free.
How compatible is Perry with Node.js and npm packages?
Perry reports approximately a 97% pass rate on Node’s own test suite across 53 node:* modules. That is a substantial signal, but it is not a promise that every Node API, edge case, native addon, or npm package will work. The result is feature-specific and should be treated as a project claim that changes as the implementation evolves.
Perry also tracks popular packages and describes Node-compatible APIs. Before migrating, inventory the exact modules your application imports, including transitive dependencies and packages that use dynamic evaluation, native addons, filesystem assumptions, or undocumented Node behavior. A package passing a smoke test is not proof that its error handling, streaming, worker, and shutdown paths behave identically.
The scriptc comparison describes an npm strategy that is dynamic-island by default, with experimental static compilation. That suggests a more cautious adoption path: keep packages that need JavaScript semantics in a dynamic region while progressively moving suitable code to the static compiler. Because the available evidence does not include a complete scriptc API list or current package matrix, verify support in its first-party repository before committing to a dependency-heavy application.
Recommended Free Tools
Is Perry faster than scriptc?
No defensible public result establishes a universal Perry-versus-scriptc performance winner. Perry has published workload numbers, but the cited comparison does not provide an equivalent scriptc run under the same hardware, compiler revision, inputs, and measurement rules.
Perry’s benchmark refresh is dated May 14, 2026 and uses version 0.5.908 on an Apple M1 Max with 64 GB of memory. The benchmark README reports medians from 11 runs per cell, retains p95, standard deviation, minimum, maximum, and peak RSS, and performs three untimed warmups. Node is measured from precompiled .mjs files, while Bun runs .ts directly. Perry labels the evidence pre-1.0 and warns that results can regress.
| Workload | Perry | Node | Bun | Rust | What the result shows |
|---|---|---|---|---|---|
| Image convolution | 354 ms | 1,207 ms | 915 ms | 392 ms | Perry is substantially faster than the two JavaScript runtimes in this test and close to Rust |
| Recursive Fibonacci | 309 ms | 987 ms | 518 ms | 316 ms | Perry is close to Rust and faster than Node and Bun for this CPU-bound recursion |
| JSON pipeline, 500,000 records (108 MB) | 1,649 ms | 1,010 ms | 647 ms | 604 ms | Perry is slower than all three comparison entries in this data-processing case |
| Method calls | 35 ms | 11 ms | 8 ms | Not stated | The native compiler does not win every small-operation test |
| Matrix multiply | 19 ms | 33 ms | 33 ms | Not stated | Perry is faster than the two listed JavaScript runtimes in this example |
| JSON roundtrip | 144 ms | 379 ms | 219 ms | Not stated | Perry outperforms both listed JavaScript runtimes in this example |
These figures are medians for the stated benchmark cells, not guarantees for your application. The 108 MB JSON result is especially important because it prevents a simplistic “native always wins” conclusion. Data representation, allocation, parsing, foreign-function calls, and runtime compatibility layers can dominate the cost of a workload.
The independent js-compiled harness evaluates five axes: execution time, peak memory, artifact size, compile time, and coverage. Its results run in GitHub Actions, which is useful for repeatability but not directly interchangeable with Perry’s Apple M1 Max measurements. For a fair decision, pin each compiler commit, use identical inputs, run warm and cold starts separately, and record medians plus tail latency, memory, binary size, and build time.
What do binary size and deployment requirements look like?
Perry reports a hello-world binary of roughly 330 KB and a MongoDB graphical application of roughly 7 MB. Those examples show that application size depends heavily on linked features; they are not a minimum, maximum, or promise for every target.
No comparable scriptc artifact sizes are established in the available comparison. A statically compiled scriptc program may avoid a full JavaScript engine, while a dynamic build that embeds quickjs-ng necessarily carries runtime code. Measure both modes with the same linker settings and stripped or unstripped policy you will use in production.
Deployment planning should include more than the executable:
- Record whether the target needs a dynamic runtime, system libraries, or platform-specific permissions.
- Measure cold-start time separately from steady-state throughput.
- Check whether native UI assets, fonts, WebAssembly modules, and package data are bundled or loaded externally.
- Verify reproducibility by building from a pinned compiler version and lockfile.
- Test upgrades because both projects are moving quickly and pre-1.0 behavior can change.
Can either compiler replace Node.js?
Neither should be treated as a drop-in replacement for every Node.js service. Perry’s native path can remove the JavaScript engine, but its roughly 97% result across 53 node:* modules still leaves API-specific gaps and does not cover every third-party package. scriptc’s static mode removes the engine for eligible code, while dynamic mode intentionally keeps quickjs-ng for code that needs JavaScript semantics.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →A realistic migration is selective. A self-contained command-line utility, image processor, or CPU-heavy worker is a better first candidate than a framework that depends on runtime reflection, native addons, hot reloading, or undocumented Node internals. Keep the original Node implementation as an oracle during migration and compare outputs, errors, resource use, and shutdown behavior.
Which compiler should you choose for a new project?
Choose based on the product constraints rather than a headline benchmark.
| Your priority | More suitable starting point | Reason |
|---|---|---|
| One TypeScript codebase for desktop, Apple, Android, and web/WASM | Perry | Those target families and a broader application stack are documented |
| Native UI and OS-threaded application behavior | Perry | Native UI and real OS threads are part of its published scope |
| Node-compatible APIs and an existing package ecosystem | Perry, after an API audit | It reports broad Node test coverage and package integrations, but support remains feature-specific |
| A strict, inspectable boundary between native and JavaScript execution | scriptc | Static, dynamic, and rejected categories are explicit |
| Gradual migration of packages through dynamic islands | scriptc | The comparison describes dynamic npm support with experimental static compilation |
| Proven performance for one specialized workload | Whichever wins your controlled test | Published Perry results vary by workload, and no equivalent scriptc benchmark is available |
For teams building a complete product, Perry is the lower-friction investigation. For compiler-oriented teams that value a small, understandable execution contract and are willing to supply more application infrastructure themselves, scriptc may be the better experiment.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.How should you evaluate Perry or scriptc before committing?
A short, representative proof of concept is more informative than a toy benchmark. Use the same source tree and acceptance tests for both compilers where possible.
- Freeze the workload: choose a real command, service endpoint, or UI workflow and record representative input sizes, error cases, and concurrency.
- Map dependencies: list direct and transitive npm packages, Node built-ins, native addons, dynamic imports, file-system access, networking, workers, and serialization formats.
- Build the smallest vertical slice: include startup, one successful operation, one failure path, logging, and clean shutdown rather than only a hot loop.
- Classify unsupported behavior: for scriptc, mark each dependency static, dynamic, or rejected. For Perry, identify which APIs use native implementations and which require compatibility runtime behavior.
- Test every target: compile the exact desktop, Apple, Android, or web/WASM targets you intend to ship. A successful desktop build says nothing about mobile or browser output.
- Measure five dimensions: execution time, peak memory, artifact size, compile time, and coverage. Add cold start, p95 latency, and energy or battery impact when relevant.
- Compare correctness: run golden-output tests, malformed-input tests, cancellation, timeouts, filesystem permissions, network failures, and process termination.
- Repeat after a clean build: use pinned revisions, identical optimization settings, and several runs. Keep warmups and measurement windows documented.
- Review operational tooling: inspect debugging, source maps, crash reports, profiling, cross-compilation, signing, and update delivery before declaring the prototype production-ready.
Install Perry through the project’s documented npm, Homebrew, or winget paths, then verify the compiler version and target toolchain. For scriptc, use its current first-party instructions and confirm whether the selected build embeds quickjs-ng. The available comparison does not establish stable command names, release channels, or licensing terms for scriptc, so do not copy an old command from an undated blog post into automation.
What are the main risks and unknowns?
- Version volatility: Perry’s published benchmark is explicitly pre-1.0, and both projects can change behavior between revisions.
- Uneven API coverage: a high aggregate Node test pass rate can hide a missing method that your application uses on every request.
- Runtime surprises: dynamic execution may change memory, startup, security, and observability characteristics compared with static code.
- Platform asymmetry: a feature documented for desktop may not yet have equivalent support on Apple, Android, or web/WASM targets.
- Benchmark mismatch: different CPUs, input data, warmup policies, and precompilation choices can reverse a ranking.
- Unstated scriptc details: the available comparison does not establish its current license, complete API list, or platform matrix; verify those directly before adoption.
Mitigate these risks by pinning versions, keeping a fallback build, and treating unsupported features as explicit acceptance criteria. A compiler that is slightly slower but predictable and supported on every target can be cheaper to operate than a faster prototype that requires extensive platform-specific rewrites.
Best Value
What is the practical verdict?
Perry is the stronger default when you want a broad native application stack, multiple client platforms, native UI, OS threads, and a path from existing Node-oriented TypeScript. Its benchmark data is promising on several CPU-heavy examples, but the JSON pipeline and small method-call test show why workload measurements remain essential.
scriptc is compelling when the compilation contract itself is the priority. Its typed IR, explicit static/dynamic/rejected boundaries, and quickjs-ng escape hatch let a team decide exactly where native guarantees end. That clarity comes with more responsibility for platform support, UI, package compatibility, and production tooling.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Build both against the same representative slice if the decision is important. The winning compiler is the one that meets your required targets, passes your compatibility suite, and delivers acceptable latency, memory, artifact size, and build time without hiding unsupported behavior.
Frequently Asked Questions
Does Perry’s native output always run without JavaScript at runtime?
Only the parts that use its native compilation and runtime implementations can make that guarantee. Compatibility features may rely on optional runtime behavior, so inspect the generated target and the API-specific documentation rather than assuming every package is engine-free.
Can scriptc’s dynamic mode be removed later?
Potentially, if the dependency or code path becomes supported by the static compiler. Treat that as a migration project: isolate the dynamic boundary, add tests for equivalent behavior, and re-measure memory and startup after replacing it.
Why might a native compiler lose on a JSON benchmark?
Parsing, allocation, object-shape handling, and conversion between runtime representations can dominate a data pipeline. Native code generation helps only when the surrounding representation and library implementations are also efficient for that workload.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
What should I verify about scriptc before using it commercially?
Confirm the current license, supported operating systems and architectures, release cadence, debugging tools, and API compatibility in its first-party repository. Those details are not established by the available comparison and can materially change the cost of production adoption.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

