You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Confirmed real, and already resolved on the current v3 tip.
Nightly numbers (v3)
Run
v3 commit
1k
10k
2026-10-18
b21708a3
15.0 ms
1.12 s
2026-10-19
d87dfff8
210.6 ms
20.95 s
2026-10-20
84ac8457
163.9 ms
16.34 s
Cause. Bisected with the same rule query and fixture (1k entities, 10% blocked): the step is 491049e0 (#624, "compare imported values by join equality on every executor path", #546): 17.5 → 206 ms at 1k. Since then StratifiedEvaluator matches each candidate row's not body with match_patterns_seeded from a one-row seed. That takes join_with_pattern's hash-join path, which scans every fact and builds bindings for every :blocked fact once per outer row. The old literal substitution matched only 0–1 facts per row. main has no seeded_body_rows, so this was v3-only.
Resolution.#670 (#548, Recursive operator) runs rule queries on the streaming engine, which bypasses this path. Local timings (laptop, noisy):
v3 tip df7282f1: 2.5 ms at 1k, 27 ms at 10k, well below the pre-regression baseline
Remaining. The executor/evaluator path still runs negation bodies per row this way (StratifiedEvaluator, evaluate_not_join, not_body_matches). It only runs when the engine can't plan a query, and under the test oracle. #551 removes it.
Closing; the next v3 nightly should confirm the numbers.
Activity
adityamukho commentedon Oct 21, 2026
Confirmed real, and already resolved on the current
v3tip.Nightly numbers (v3)
b21708a3d87dfff884ac8457Cause. Bisected with the same rule query and fixture (1k entities, 10% blocked): the step is
491049e0(#624, "compare imported values by join equality on every executor path", #546): 17.5 → 206 ms at 1k. Since thenStratifiedEvaluatormatches each candidate row'snotbody withmatch_patterns_seededfrom a one-row seed. That takesjoin_with_pattern's hash-join path, which scans every fact and builds bindings for every:blockedfact once per outer row. The old literal substitution matched only 0–1 facts per row.mainhas noseeded_body_rows, so this was v3-only.Resolution. #670 (#548, Recursive operator) runs rule queries on the streaming engine, which bypasses this path. Local timings (laptop, noisy):
2bef68a7(feat(engine): rule queries on the streaming engine (#548 PR 2) #670): 7.5 ms at 1kdf7282f1: 2.5 ms at 1k, 27 ms at 10k, well below the pre-regression baselineRemaining. The executor/evaluator path still runs negation bodies per row this way (
StratifiedEvaluator,evaluate_not_join,not_body_matches). It only runs when the engine can't plan a query, and under the test oracle. #551 removes it.Closing; the next v3 nightly should confirm the numbers.