JIT Compilation
The jit feature flag enables Just-In-Time compilation of HBAC rules via
Cranelift. It adds a hybrid JIT/interpreter runtime as an additional
optimization layer in the evaluation pipeline.
Enabling
[dependencies]
hbac-rs = { version = "0.2", features = ["jit"] }
#![allow(unused)]
fn main() {
let mut policy = HbacPolicy::new();
policy.load_rules(rules);
policy.enable_jit();
for request in requests {
policy.evaluate(&request);
}
}
enable_jit() returns false if Cranelift is not available for the
current architecture (only x86_64 is supported).
How It Works
The JIT runtime profiles rule evaluations and compiles hot rules to native code after a threshold of 100 evaluations. Rules that are not hot or cannot be compiled fall back to the standard decision tree interpreter.
flowchart TD
EVAL[evaluate request] --> JIT{JIT-compiled<br/>deny rules?}
JIT -->|match| DENY[return deny]
JIT -->|no match| INTERP[decision tree<br/>interpreter]
INTERP --> RESULT[return result]
PROFILE[profiler records<br/>evaluation count] -.-> HOT{count >= 100?}
HOT -->|yes| COMPILE[compile via Cranelift]
COMPILE --> CACHE[store in jit_cache]
The runtime checks JIT-compiled deny rules first for early exit, then delegates to the interpreter for the full evaluation.
Rule Classification
The compiler classifies each rule into a pattern that determines the compilation strategy:
| Pattern | Criteria | Compilation |
|---|---|---|
CategoryAll | All three dimensions are category=all | Native Cranelift codegen (constant return) |
SingleUser | One user name, any host/service | Optimized interpreter (direct string comparison) |
GroupMatch | User groups specified, any host/service | Optimized interpreter (set membership check) |
Complex | Multiple users, or other patterns | Standard interpreter (not compiled) |
Only CategoryAll rules produce actual native machine code. SingleUser
and GroupMatch use pattern-specific data cached at classification time for
faster interpreter evaluation, but do not generate native code.
Internals
Components
JitCompiler– Cranelift-based compiler. Owns theJITModule, declares and finalizes functions.HotRuleProfiler– LRU-based evaluation counter (256 entries). Tracks per-rule evaluation counts and identifies rules above the JIT threshold.JitRuntime– Orchestrates profiling, compilation, and evaluation. Maintains ajit_cachemapping rule names to compiled evaluators.CompiledRule– Implements theRuleEvaluatortrait. Holds either a native function pointer (CategoryAll) or pattern-specific data for the optimized interpreter fallback.
RuleEvaluator Trait
#![allow(unused)]
fn main() {
pub trait RuleEvaluator: Send + Sync {
fn evaluate(&self, request: &HbacRequest) -> bool;
fn debug_info(&self) -> String;
}
}
All compiled rules implement this trait. CompiledRule dispatches to the
native function pointer when available, otherwise uses the cached pattern
data.
Safety
CompiledRule contains a raw function pointer to JIT-compiled code. The
pointer is safe because:
- It is obtained from
JITModule::get_finalized_function()after finalization - The backing
JITModuleis owned byJitCompiler, which is owned by the sameJitRuntimethat owns theCompiledRulein itsjit_cache - The compiled code is read-only after finalization (
Send + Sync)
Statistics
#![allow(unused)]
fn main() {
let stats = policy.jit_stats();
println!("total: {}", stats.total_rules);
println!("compiled: {}", stats.jit_compiled);
println!("hot: {}", stats.hot_rules);
}
jit_compile_hot() manually triggers compilation of all rules that have
crossed the profiling threshold:
#![allow(unused)]
fn main() {
policy.jit_compile_hot();
}
Performance Impact
See Performance Results for measured JIT impact at each scale. Summary:
- Cached workloads: no measurable difference (LRU cache dominates)
- Uncached workloads: ~8-12% throughput improvement
- Build time: no consistent overhead
JIT is worth enabling when uncached or low-hit-rate workloads dominate. For typical SSSD deployments with high cache hit rates, it provides no benefit.
Binary Size
The jit feature adds ~500 KB from Cranelift dependencies.
See Also
- Architecture Overview – JIT layer in the evaluation flow
- Performance Results – benchmark data