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:
[dependencies]
navi-vm = { version = "...", features = ["jit"] }Then enable JIT on the instance builder:
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:
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
| Platform | JIT status |
|---|---|
| x86-64 (Linux / macOS / Windows) | Supported |
| AArch64 (Apple Silicon, Linux ARM64) | Supported |
| Other architectures | Falls 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/secfrombench.rs(excludes init/build time)
Commands used:
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| Mode | Non-JIT runtime | JIT runtime | Speedup | Non-JIT bars/sec | JIT bars/sec |
|---|---|---|---|---|---|
| Stream | 44.58s | 39.34s | 1.13x | 224,298 | 254,171 |
| Chart | 43.18s | 38.65s | 1.12x | 231,609 | 258,765 |
Observed RSS on this run:
| Mode | Non-JIT final RSS | JIT final RSS |
|---|---|---|
| Stream | 23.9 MB | 54.3 MB |
| Chart | 1351.6 MB | 1389.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
- Integration Overview — full topic summary for the integration guide