Skip to content

feat(evaluation): pre-evaluate static flags for host-side caching#68

Merged
aepfli merged 1 commit into
mainfrom
feat/pre-evaluate-static-flags
Feb 10, 2026
Merged

feat(evaluation): pre-evaluate static flags for host-side caching#68
aepfli merged 1 commit into
mainfrom
feat/pre-evaluate-static-flags

Conversation

@aepfli
Copy link
Copy Markdown
Contributor

@aepfli aepfli commented Feb 10, 2026

Summary

  • Pre-evaluate static (no targeting) and disabled flags during update_state() and return results in the response
  • Java FlagEvaluator caches these results and returns them directly from evaluateFlag(), skipping the WASM boundary entirely
  • Updates Java README with JMH benchmark comparison data (WASM vs native JsonLogic)

Motivation

JMH benchmarks showed a ~200x latency gap for simple flags: native JsonLogic at 0.022 µs/op vs WASM at 4.41 µs/op. The overhead comes from JSON serialization across the WASM boundary — but static flags don't need any of that, they always return the same result.

Changes

Rust

  • src/model/mod.rs: Added pre_evaluated: Option<HashMap<String, EvaluationResult>> to UpdateStateResponse
  • src/evaluator.rs: Added pre_evaluate_static_flags() that evaluates all static/disabled flags with empty context during update_state()

Java

  • UpdateStateResult.java: Added preEvaluated map field
  • FlagEvaluator.java: Added volatile cache populated on updateState(), checked first in evaluateFlag() — cache hit skips WASM entirely
  • README.md: Updated Performance section with benchmark comparison tables

Expected performance impact

Scenario Before After
Simple flag (no targeting) ~4.41 µs/op ~0.02 µs/op (HashMap lookup)
Disabled flag ~4.41 µs/op ~0.02 µs/op (HashMap lookup)
Targeting flag ~26 µs/op ~26 µs/op (unchanged)

Test plan

  • cargo test — all Rust tests pass
  • cargo clippy -- -D warnings — clean
  • cargo fmt -- --check — clean
  • ./mvnw test — all 30 Java tests pass (existing tests exercise static flags via cache)

Closes #60

🤖 Generated with Claude Code

…e caching

Static flags (no targeting rules) and disabled flags always return the
same result regardless of context. Pre-evaluate them during update_state()
and include results in the response so hosts can cache them and skip the
WASM boundary entirely.

Rust: UpdateStateResponse gains a preEvaluated map populated by a new
pre_evaluate_static_flags() helper in FlagEvaluator::update_state().

Java: FlagEvaluator stores the map in a volatile cache that is replaced
atomically on each updateState(). evaluateFlag() checks the cache first
and returns immediately on hit, avoiding all WASM overhead for simple
flags (~4.4µs → ~0.02µs).

Closes #60

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aepfli aepfli merged commit 0867574 into main Feb 10, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf: Pre-evaluate flags without targeting to eliminate WASM overhead

1 participant