Skip to content

JIT Compilation

Navi includes an optional JIT compiler that compiles Navi scripts to native machine code at build time. For compute-intensive scripts running across many bars, JIT can deliver significant throughput improvements.

Enabling JIT

JIT support is a compile-time feature flag. Add the jit feature to your dependency:

toml
[dependencies]
navi-vm = { version = "...", features = ["jit"] }

Then enable JIT on the instance builder:

rust
let mut instance = Instance::builder(bars, source, TimeFrame::days(1), "NASDAQ:AAPL")
    .with_jit(true)
    .build()
    .await?;

with_jit is only available when the jit feature is active. To write code that compiles with or without the feature, use a conditional:

rust
let mut builder = Instance::builder(bars, source, TimeFrame::days(1), "NASDAQ:AAPL");

#[cfg(feature = "jit")]
{
    builder = builder.with_jit(true);
}

let mut instance = builder.build().await?;

When to Use JIT

JIT is most beneficial for:

  • Long historical backtests — scripts running over tens of thousands of bars.
  • Many parallel instances — compilation cost amortizes quickly when the same instance is reset and re-run repeatedly.
  • Compute-heavy scripts — scripts with dense arithmetic, loops, or many function calls.

JIT adds latency to build(). For short scripts or a small number of bars the build overhead may outweigh the execution gain. Profile before enabling JIT in production.

Platform Support

PlatformJIT status
x86-64 (Linux / macOS / Windows)Supported
AArch64 (Apple Silicon, Linux ARM64)Supported
Other architecturesFalls back to interpreter

On unsupported architectures, with_jit(true) is a no-op and execution falls back to the interpreter transparently.

Benchmark Snapshot

The following numbers were measured on this machine with the bundled benchmark tool:

  • CPU: 12th Gen Intel(R) Core(TM) i9-12900K
  • Build profile: release
  • Script: website/naviscripts/indicators/SimpleMovingAverage.nvs
  • Workload: 100 instances x 100,000 bars
  • Metric: benchmark Run time / Bars/sec from bench.rs (excludes init/build time)

Commands used:

bash
cargo run --release -p rust-examples --bin bench -- website/naviscripts/indicators/SimpleMovingAverage.nvs
cargo run --release -p rust-examples --features jit --bin bench -- website/naviscripts/indicators/SimpleMovingAverage.nvs
ModeNon-JIT runtimeJIT runtimeSpeedupNon-JIT bars/secJIT bars/sec
Stream44.58s39.34s1.13x224,298254,171
Chart43.18s38.65s1.12x231,609258,765

Observed RSS on this run:

ModeNon-JIT final RSSJIT final RSS
Stream23.9 MB54.3 MB
Chart1351.6 MB1389.0 MB

Treat these as a point-in-time reference, not a guarantee. Actual gains depend on script structure, bar count, instance count, allocator behavior, and whether your workload is dominated by build time or execution time. On this script, JIT improved execution throughput modestly but did not reduce chart-mode memory usage.

Next Steps

Released under the MIT License.