New to Rayzor? Start with compilation modes, tiering, and memory management. Read the docs →
alpha Haxe 4.x, natively →

Instant Haxe.
Native performance.

Run Haxe with instant startup and a JIT that optimizes your code as it runs. Memory is managed without a garbage collector.

Get started GitHub
Particles.hx
// hot loop compiled after ~1k calls
class Particles {
  static function update(p:Array<Particle>, dt:Float) {
    for (i in 0...p.length) {
      var q = p[i];
      q.vy += 9.81 * dt;
      q.x += q.vx * dt;
      q.y += q.vy * dt;
    }
  }

  static function main() {
    var world = Particle.spawn(100000);
    for (frame in 0...1200) update(world, 1/60);
  }
}
Try it in the playground → edit, compile and run in the browser
coming soon
$ rayzor run Particles.hx
tier 0 · interp first output at 38ms
profile update() hot, 1,024 calls
tier 1 · compiled compiled in 4.2ms
tier 3 · optimized compiled in 61ms, -O2
steady state 3.1× interpreter throughput
<50ms
to first output. The interpreter runs before anything is compiled
Tiered
starts in the interpreter and compiles frequently called functions
Hot reload
swap a changed module into a running program without restarting it
0 GC
the compiler inserts cleanup based on where values are used
Native + wasm
native binaries and WebAssembly from a shared optimization pipeline
Targets

Desktop, server, and the browser.

Use the same Haxe codebase and runtime on Linux, macOS, Windows, and the web. WebAssembly goes through the same compiler and optimizations as native code, with output as a core module, WASI P2 component, or browser bundle.

Linux
x86_64 · aarch64

Run from source with instant startup during development, then build a native binary to deploy. Includes the full runtime, threads, sockets, and NUMA-aware worker pinning.

rayzor aot main.hx -o app
macOS
aarch64 · x86_64

Native builds on Apple silicon and Intel, with a worker pool that adapts to the available CPU topology.

rayzor aot main.hx -o app
Windows
x86_64 · MSVC

Build native binaries with the MSVC toolchain, or use the tiered JIT to run from source.

rayzor aot main.hx -o app.exe
WebAssembly
core modules · WASI P2

Build a core module or WASI P2 component. Add --browser to generate an HTML harness for running it in a browser.

rayzor build --target wasm --browser
Cross-compile --target <triple> --sysroot <dir> --linker <path> --target wasm-wasi
Design choices

Why build another
Haxe compiler?

We wanted native code, fast iteration, and control over memory while keeping Haxe's types and macros. Rayzor brings those pieces together in one compiler. These choices guide the implementation.

01 Correctness first

We verify optimizations before shipping them. Drop insertion and required inlining run at every level, including -O0, because program correctness depends on them.

02 No garbage collector

The compiler determines when to free memory, so there are no GC pauses during a frame. You can add ownership annotations one class at a time.

03 Analysis is shared

Dominance, loop structure and escape info are computed once and reused by every pass that needs them.

04 Deterministic codegen

MIR collections use a stable iteration order to keep code generation reproducible.

05 Cache unchanged modules

Parsing, type checking, and bundling reuse cached work for unchanged modules. The cache is enabled by default.

06 Shared optimization passes

Every target uses the same optimized MIR. Improvements to the shared passes carry through to both native binaries and WebAssembly.

Scope

Rayzor focuses on native code and WebAssembly. For JavaScript, Python, or PHP output, use the official Haxe compiler.

Memory

Memory without GC pauses.

The compiler tracks where values are last used and inserts cleanup at those points. Add ownership annotations where you need to control sharing.

@:move class Texture {
  public var pixels:Bytes;
}

@:arc class Atlas {
  public var pages:Array<Texture>;
}

@:safety(strict)
class Main {
  static function main() {
    var t = new Texture();
    upload(t);
    // upload(t);  ← error: use after move
  }
}
@:moveUnique ownership

Move semantics, no aliasing. Use-after-move is a hard error, caught before you run.

@:arcShared across threads

Atomic reference counting for values shared across threads.

@:deriveChecked concurrency

Send and Sync markers, validated against Thread, Channel, Mutex and Arc.

@:safetyAdopt it incrementally

Strict mode requires every class to be annotated; non-strict wraps the rest in Rc. You can add annotations one class at a time.

Benchmarks

Benchmark results.

We run the same Haxe source on every target. Rayzor beats HashLink and the JVM, avoids JVM startup overhead, and outperforms hxcpp on floating-point workloads. Compilation takes tens of milliseconds, compared with hundreds on the other targets.

Short compile times make a difference when you run code throughout the day. Rayzor needs no C++ toolchain or JVM warm-up, and you can run source files directly. rayzor run starts executing while the optimizer runs. These are cold-build measurements. With the BLADE cache, unchanged modules are already compiled, so compilation on the second build is instant.

10 measured iterations, mean reported. AMD EPYC 7763 64-Core Processor, linux, x86_64, 2026-10-23.

Full results, regenerated by CI ↗
Rayzor · tiered 746ms1.03×
hxcpp 727msfastest
Haxe/JVM 969ms1.33×
HashLink/C 1.48s2.04×
HashLink 1.36s1.87×
Ash 748ms1.03×
lower is better

execution only, mean of 10 measured runs · milliseconds, smaller is better
axis clips at 4× the fastest. ▸ marks a bar past the edge, real value labeled

SIMD

SIMD types with
Haxe operators.

The SIMD* types cover 128- and 256-bit vectors with float and integer lanes. You can use tuple and array literals, arithmetic operators, and methods such as dot, normalize, magnitude, and lerp. The compiler emits NEON, SSE2, or WASM SIMD128 instructions, with a scalar fallback where needed.

The interpreter supports vector types, and SIMD functions are compiled on their first call. Vector work runs as compiled code from the start, while startup stays instant.

SIMD types and backend support ↗
Vectors.hx
import rayzor.SIMD4f;

var a:SIMD4f = (1.0, 2.0, 3.0, 4.0);
var b = SIMD4f.splat(2.0);
var c = a * b + a;
var d = a.dot(b);
var n = a.normalize();
Get started

Install and run.

Point Rayzor at a .hx file, or hand it the build.hxml you already have.

runtiered JIT, cache on by default
aotwhole program compiled ahead of time to a native binary
bundleone portable .rzb that skips compilation
buildnative, wasm or wasm-wasi from a manifest
$ curl -fsSL https://rayzor.tech/install.sh | sh
Installs to ~/.rayzor/bin with everything needed to run Rayzor.
then
$ rayzor init --name my-app
$ rayzor run src/Main.hx
Hello, Rayzor
tier 0 → 1 → 3 · 41ms total
Who it's for

What you can build.

Servers

Rayzor determines cleanup at compile time, so long-running services avoid latency spikes from garbage collection. OS threads and channels handle concurrent work, and the server preset optimizes for processes that stay up.

The server preset optimizes aggressively for processes that stay up
OS threads with Channel, Select, Mutex and Arc
Deploy a native binary, or an .rzb bundle that skips source compilation
rayzor aot --preset server Channel<T> 0 GC pauses
Game development

Keep GC pauses out of the frame budget. Ownership annotations make allocation lifetimes explicit, and the JIT lets you iterate without waiting for a full build.

@:move and @:arc where aliasing matters; everything else stays ordinary Haxe
SIMD4f with operator overloads for transforms, physics and batch math
@:shader classes compile to WGSL
@:cstruct provides flat, headerless layouts for C ABI compatibility
SIMD4f @:shader → WGSL @:move @:cstruct
High-performance computing

Write compute kernels with vector types, persistent worker threads, and explicit CPU affinity. The Nue inference engine below uses these APIs.

128- and 256-bit vectors with widening dot-accumulate for quantized kernels
SpinPool keeps workers alive and chunk-steals, so dispatch costs a few atomic stores
WorkerPool pins one worker per NUMA node so memory lands first-touch on the right controller
SIMD8i32 SpinPool WorkerPool CpuTopology
Case study · Nue

An LLM inference engine,
written in Haxe.

Nue runs local language models on the Rayzor runtime. The tokenizer, the quantized matmul kernels, the KV cache and the scheduler are all written in Haxe.

We benchmark every kernel against the Rust version it replaces. When Haxe is slower, we work on the kernel, thread pool, or compiler until it catches up.

Browse nue/ in the repo
quantized matmul KV cache SpinPool SIMD kernels GGUF
Decode throughput Apple M1 Pro · 16GB
Qwen 0.5B 138tok/s
Llama 1B 90tok/s
Pure Haxe vs the Rust kernel

Qwen2.5-0.5B, interleaved arms, medians, verified with zero FFI calls.

schemeHaxeRust Q6_K · k-quant + Q8_0 135.63 106.30 Q5_0 → INT8 113.82 119.37

The Haxe k-quant kernel is faster than the Rust version. INT8 is within 5%, and the gap is narrowing. Nue uses FFI for platform APIs such as AMX, CoreML, and VNNI; the compute kernels stay in Haxe.

In progress

Using the official Haxe frontend.

We're working on reading typed output from the official Haxe compiler and lowering it to Rayzor MIR. This would let you keep your existing frontend, macros, and libraries, with Rayzor handling native code generation, ownership, and tiered execution.

The aim is to compile your existing Haxe build to machine code without changing the source.

Follow the discussion ↗
haxe Your existing build, run by the official compiler. Same class paths, same macros
typed output Its typed output read directly, instead of Rayzor re-parsing your source
→ MIR Lowered into the same SSA every Rayzor backend already consumes
native Ownership analysis, the optimization pipeline and the tiered runtime, unchanged