Skip to content

BE-428: HashQL: Simplify traversal tracking to path recording#8498

Open
indietyp wants to merge 32 commits intomainfrom
bm/be-428-hashql-simplify-traversal-tracking-to-path-recording
Open

BE-428: HashQL: Simplify traversal tracking to path recording#8498
indietyp wants to merge 32 commits intomainfrom
bm/be-428-hashql-simplify-traversal-tracking-to-path-recording

Conversation

@indietyp
Copy link
Member

@indietyp indietyp commented Mar 2, 2026

🌟 What is the purpose of this PR?

Replaces the traversal extraction transform pass (which rewrote MIR bodies by splicing load statements and creating new locals) with a pure analysis pass that records which entity paths each block accesses as bitsets. Introduces per-block path transfer cost charging so the placement solver can account for data locality when assigning blocks to backends.

🔍 What does this change?

  • Traversal analysis (traversal/analysis/): walks the body, resolves vertex projections via EntityPath::resolve(), records accessed paths as TraversalPathBitSet. No MIR mutation.
  • Per-block cost analysis (cost/analysis.rs): new BasicBlockCostAnalysis combines per-statement costs with a path transfer premium. For each block, charges a transfer premium on targets that are not the natural origin for the accessed paths (e.g., Interpreter pays a premium for Vectors because Embedding is the origin). Premiums are charged once per block, not per statement.
  • BasicBlockCostVec: the placement solver now operates on precomputed per-block costs. PlacementSolverContext takes blocks: &BasicBlockCostVec instead of separate statement costs and assignment arrays.
  • BlockPartitionedVec<T>: generic offset-table-backed per-block storage, extracted from StatementCostVec internals.
  • TraversalLattice: lattice structure carrying VertexType for dataflow analysis over path bitsets.
  • EntityPath::origin(), EntityPath::estimate_size(): per-path origin backend and transfer size estimation.
  • TransferCostConfig: variable-size parameters (properties, embeddings, provenance sizes, per-target cost multiplier).
  • FiniteBitSet::negate() in hashql-core.
  • Removed pass/transform/traversal_extraction/ (the MIR transform and its tests).

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

⚠️ Known issues

Path transfer premiums use pure over-approximation: every non-origin backend pays the full premium with no discounting for co-location. This can over-penalize non-origin assignment when multiple blocks access the same path on the same backend (cross-block dedup is not implemented). This is intentional: separable costs are a prerequisite for the PBQP solver planned in BE-436.

The ideal cost model is non-separable: the first block on a backend pays the full data fetch cost, subsequent co-labeled blocks pay zero ("shared-fetch" / pay-once-per-group). This maps to submodular clique costs in the optimization literature. Two frameworks formalize this:

  • Jegelka et al. 2014 (arXiv:1402.0240, Cooperative Graph Cuts): the "label cost" special case is mathematically identical to shared-fetch. Algorithms include polymatroidal flow (exact for separable surrogates) and semigradient methods. However, all are binary-only (k=2 labels).
  • Kolmogorov et al. 2010 (arXiv:1006.1990, Sum of Submodular Functions): general framework via submodular flow with capacity scaling. Also binary-only.

The multi-label extension via alpha-expansion (Boykov, Veksler, Zabih 2001) reduces k-label to a sequence of binary cooperative cuts (each solvable exactly), but only guarantees a local minimum. Our TransMatrix is not metric, so no global approximation factor holds. For k=3 backends (growing to 6-7), the overhead of iterative cooperative cut calls on ~100-node graphs is not justified when PBQP R1/R2 reductions on the separable over-approximation give exact solutions in microseconds.

Pure over-approximation does not distort the relative ranking between non-origin backends (the premium cancels in pairwise comparisons) but inflates the absolute cost of non-origin assignment, biasing toward origin backends. Intra-block dedup (implemented here) is the first mitigation; cross-block dedup remains an open problem for k > 2 on cyclic graphs.
:

🛡 What tests cover this?

  • Unit tests for BasicBlockCostAnalysis covering: no vertex access, single origin/non-origin paths, multiple path accumulation, composite path expansion, restricted target domains, cross-block independence
  • Unit tests for TraversalAnalysisVisitor covering path resolution from MIR projections
  • Unit tests for EntityPathBitSet covering composite swallowing, lattice operations, normalization
  • Existing solver tests updated to use BasicBlockCostVec; new path_premiums_influence_placement and provenance_variants_produce_different_premiums integration tests
  • End-to-end mixed_postgres_embedding_interpreter test verifying three-backend splitting

❓ How to test this?

  1. cargo nextest run --package hashql-mir
  2. cargo test --package hashql-mir --doc

feat: checkpoint (II)

feat: checkpoint (III)

feat: snapshot vec

feat: add dedicated filter

feat: checkpoint

feat: filter implementation

feat: filter implementation (mostly) done

chore: environment capture note

chore: always postgres bigint

feat: target clone

feat: simplify lookup

feat: move storage up

feat: eval entity path

chore: checkpoint

chore: checkpoint

chore: find entrypoint

feat: eval context

feat: eval cleanup

chore: cleanup

feat: track index

feat: wire up filter

feat: add error reporting

chore: checkpoint
@github-actions github-actions bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team area/tests New or updated tests labels Mar 2, 2026
@cursor
Copy link

cursor bot commented Mar 2, 2026

PR Summary

High Risk
High risk because it refactors the MIR execution planning pipeline (liveness/traversal tracking, cost aggregation, and CSP solver inputs), which can change backend placement decisions and performance characteristics. It also expands use of unstable const traits/functions in core ID/bitset primitives, which may impact compilation on supported toolchains.

Overview
Replaces traversal extraction (a MIR-rewriting transform) with a pure traversal analysis that records accessed vertex EntityPaths as TraversalPathBitSets, and threads this through TraversalLivenessAnalysis and IslandPlacement.

Updates execution planning to compute per-basic-block costs (BasicBlockCostAnalysis/BasicBlockCostVec) by combining per-statement costs with a path transfer premium on non-origin backends, and changes the placement solver/CSP to consume these block costs instead of raw statement sums.

Refactors cost storage via a generic BlockPartitionedVec, adjusts PostInline construction and benches/tests accordingly, and extends core utilities (new FiniteBitSet::negate, const-ified Id/bitset traits and range helpers, plus tuple lattice combinators and InformationRange::midpoint).

Written by Cursor Bugbot for commit e6439e0. This will update automatically on new commits. Configure here.

@codecov
Copy link

codecov bot commented Mar 2, 2026

Codecov Report

❌ Patch coverage is 95.70552% with 98 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.76%. Comparing base (bb10349) to head (e6439e0).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
.../hashql/mir/src/pass/execution/traversal/entity.rs 79.51% 41 Missing and 1 partial ⚠️
...cal/hashql/mir/src/pass/execution/traversal/mod.rs 81.01% 15 Missing ⚠️
libs/@local/hashql/core/src/id/mod.rs 0.00% 9 Missing ⚠️
...ql/mir/src/pass/analysis/dataflow/lattice/impls.rs 90.10% 7 Missing and 2 partials ⚠️
...ibs/@local/hashql/mir/src/pass/execution/vertex.rs 68.18% 6 Missing and 1 partial ⚠️
...s/@local/hashql/mir/src/pass/execution/cost/mod.rs 75.00% 5 Missing ⚠️
libs/@local/hashql/core/src/id/bit_vec/mod.rs 85.00% 3 Missing ⚠️
libs/@local/hashql/mir/src/body/place.rs 0.00% 3 Missing ⚠️
libs/@local/hashql/mir/src/pass/execution/mod.rs 92.00% 1 Missing and 1 partial ⚠️
...hql/mir/src/pass/analysis/dataflow/liveness/mod.rs 96.96% 0 Missing and 1 partial ⚠️
... and 2 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8498      +/-   ##
==========================================
+ Coverage   62.65%   62.76%   +0.11%     
==========================================
  Files        1312     1316       +4     
  Lines      133689   134383     +694     
  Branches     5510     5499      -11     
==========================================
+ Hits        83757    84343     +586     
- Misses      49018    49129     +111     
+ Partials      914      911       -3     
Flag Coverage Δ
apps.hash-ai-worker-ts 1.40% <ø> (ø)
apps.hash-api 0.00% <ø> (ø)
local.hash-graph-sdk 7.73% <ø> (ø)
local.hash-isomorphic-utils 0.00% <ø> (ø)
rust.hash-graph-api 2.64% <ø> (ø)
rust.hashql-ast 87.23% <ø> (ø)
rust.hashql-compiletest 29.69% <ø> (ø)
rust.hashql-core 82.35% <91.60%> (+0.06%) ⬆️
rust.hashql-eval 69.13% <ø> (ø)
rust.hashql-hir 89.06% <ø> (ø)
rust.hashql-mir 92.34% <95.97%> (-0.26%) ⬇️
rust.hashql-syntax-jexpr 94.05% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 2, 2026

Merging this PR will not alter performance

✅ 80 untouched benchmarks


Comparing bm/be-428-hashql-simplify-traversal-tracking-to-path-recording (e6439e0) with bm/be-434-hashql-entity-path-resolution-and-storage-mapping (3d9cc9d)1

Open in CodSpeed

Footnotes

  1. No successful run was found on bm/be-434-hashql-entity-path-resolution-and-storage-mapping (885a006) during the generation of this report, so f28cd5a was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Stale comment and unnecessary reverse after removing traversal costs
    • Removed the unnecessary reverse-order iteration and stale traversal-cost comment so target statement placement now reflects its order-independent behavior.

Create PR

Or push these changes by commenting:

@cursor push 58ca5bc4a4
Preview (58ca5bc4a4)
diff --git a/libs/@local/hashql/mir/src/pass/execution/mod.rs b/libs/@local/hashql/mir/src/pass/execution/mod.rs
--- a/libs/@local/hashql/mir/src/pass/execution/mod.rs
+++ b/libs/@local/hashql/mir/src/pass/execution/mod.rs
@@ -72,10 +72,7 @@
 
         let mut statement_costs: TargetArray<_> = TargetArray::from_fn(|_| None);
 
-        let mut targets = TargetId::all();
-        targets.reverse(); // We reverse the order, so that earlier targets (aka the interpreter) can have access to traversal costs
-
-        for target in targets {
+        for target in TargetId::all() {
             let mut statement = TargetPlacementStatement::new_in(target, &self.scratch);
             let statement_cost =
                 statement.statement_placement_in(context, body, vertex, &self.scratch);
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

@vercel vercel bot temporarily deployed to Preview – petrinaut March 2, 2026 21:16 Inactive
@vercel vercel bot temporarily deployed to Preview – petrinaut March 3, 2026 09:55 Inactive
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$26.9 \mathrm{ms} \pm 140 \mathrm{μs}\left({\color{gray}-0.945 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.50 \mathrm{ms} \pm 17.3 \mathrm{μs}\left({\color{gray}0.049 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1001 $$12.3 \mathrm{ms} \pm 73.6 \mathrm{μs}\left({\color{gray}0.551 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$43.3 \mathrm{ms} \pm 341 \mathrm{μs}\left({\color{gray}-0.084 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.7 \mathrm{ms} \pm 122 \mathrm{μs}\left({\color{gray}-0.422 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1526 $$24.1 \mathrm{ms} \pm 158 \mathrm{μs}\left({\color{gray}1.05 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$28.1 \mathrm{ms} \pm 162 \mathrm{μs}\left({\color{gray}-0.028 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.81 \mathrm{ms} \pm 17.1 \mathrm{μs}\left({\color{gray}0.470 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$13.3 \mathrm{ms} \pm 99.7 \mathrm{μs}\left({\color{gray}0.067 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.92 \mathrm{ms} \pm 20.1 \mathrm{μs}\left({\color{gray}-0.020 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.11 \mathrm{ms} \pm 16.1 \mathrm{μs}\left({\color{gray}-0.359 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 51 $$3.47 \mathrm{ms} \pm 16.9 \mathrm{μs}\left({\color{gray}0.510 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.39 \mathrm{ms} \pm 26.4 \mathrm{μs}\left({\color{gray}1.07 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.67 \mathrm{ms} \pm 17.3 \mathrm{μs}\left({\color{gray}-1.036 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 107 $$4.29 \mathrm{ms} \pm 30.7 \mathrm{μs}\left({\color{gray}0.330 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.60 \mathrm{ms} \pm 31.4 \mathrm{μs}\left({\color{gray}-0.069 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.54 \mathrm{ms} \pm 17.4 \mathrm{μs}\left({\color{gray}-0.694 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$4.24 \mathrm{ms} \pm 27.4 \mathrm{μs}\left({\color{gray}0.869 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.83 \mathrm{ms} \pm 15.3 \mathrm{μs}\left({\color{gray}0.211 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.78 \mathrm{ms} \pm 16.6 \mathrm{μs}\left({\color{gray}0.368 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1 $$2.89 \mathrm{ms} \pm 14.9 \mathrm{μs}\left({\color{gray}-0.478 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$3.16 \mathrm{ms} \pm 14.7 \mathrm{μs}\left({\color{gray}-0.137 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.97 \mathrm{ms} \pm 14.6 \mathrm{μs}\left({\color{gray}-0.344 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$3.25 \mathrm{ms} \pm 17.0 \mathrm{μs}\left({\color{gray}-0.251 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$3.17 \mathrm{ms} \pm 14.3 \mathrm{μs}\left({\color{gray}0.083 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.90 \mathrm{ms} \pm 16.9 \mathrm{μs}\left({\color{gray}1.48 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 25 $$3.07 \mathrm{ms} \pm 17.4 \mathrm{μs}\left({\color{gray}0.321 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.60 \mathrm{ms} \pm 20.0 \mathrm{μs}\left({\color{gray}-0.048 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.20 \mathrm{ms} \pm 20.5 \mathrm{μs}\left({\color{gray}1.84 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 26 $$3.40 \mathrm{ms} \pm 19.7 \mathrm{μs}\left({\color{gray}0.396 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.55 \mathrm{ms} \pm 18.0 \mathrm{μs}\left({\color{gray}-0.345 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.17 \mathrm{ms} \pm 15.3 \mathrm{μs}\left({\color{gray}1.49 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.44 \mathrm{ms} \pm 21.0 \mathrm{μs}\left({\color{gray}-0.104 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$41.0 \mathrm{ms} \pm 186 \mathrm{μs}\left({\color{gray}-1.006 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$78.1 \mathrm{ms} \pm 345 \mathrm{μs}\left({\color{gray}-0.504 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$45.3 \mathrm{ms} \pm 215 \mathrm{μs}\left({\color{gray}0.539 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$48.0 \mathrm{ms} \pm 235 \mathrm{μs}\left({\color{gray}-0.026 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$55.9 \mathrm{ms} \pm 311 \mathrm{μs}\left({\color{gray}-1.490 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$43.2 \mathrm{ms} \pm 165 \mathrm{μs}\left({\color{gray}-0.840 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$420 \mathrm{ms} \pm 897 \mathrm{μs}\left({\color{gray}0.147 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$97.2 \mathrm{ms} \pm 608 \mathrm{μs}\left({\color{red}5.36 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$87.3 \mathrm{ms} \pm 457 \mathrm{μs}\left({\color{gray}-0.372 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$283 \mathrm{ms} \pm 1.09 \mathrm{ms}\left({\color{gray}-0.016 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$15.8 \mathrm{ms} \pm 114 \mathrm{μs}\left({\color{gray}0.821 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$15.9 \mathrm{ms} \pm 84.7 \mathrm{μs}\left({\color{gray}0.630 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$16.0 \mathrm{ms} \pm 92.7 \mathrm{μs}\left({\color{gray}0.107 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$15.8 \mathrm{ms} \pm 91.1 \mathrm{μs}\left({\color{gray}-1.118 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$18.4 \mathrm{ms} \pm 163 \mathrm{μs}\left({\color{gray}-2.646 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$15.7 \mathrm{ms} \pm 80.7 \mathrm{μs}\left({\color{gray}1.14 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$15.6 \mathrm{ms} \pm 75.8 \mathrm{μs}\left({\color{gray}-1.454 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$15.7 \mathrm{ms} \pm 67.7 \mathrm{μs}\left({\color{gray}-0.040 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$16.2 \mathrm{ms} \pm 73.6 \mathrm{μs}\left({\color{gray}-0.394 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$23.4 \mathrm{ms} \pm 154 \mathrm{μs}\left({\color{gray}-0.025 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$29.9 \mathrm{ms} \pm 283 \mathrm{μs}\left({\color{gray}-0.347 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$30.1 \mathrm{ms} \pm 326 \mathrm{μs}\left({\color{gray}-2.627 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$31.7 \mathrm{ms} \pm 309 \mathrm{μs}\left({\color{red}7.14 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$31.1 \mathrm{ms} \pm 247 \mathrm{μs}\left({\color{gray}2.38 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$31.3 \mathrm{ms} \pm 288 \mathrm{μs}\left({\color{gray}2.51 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$30.3 \mathrm{ms} \pm 313 \mathrm{μs}\left({\color{gray}-0.936 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$30.3 \mathrm{ms} \pm 266 \mathrm{μs}\left({\color{gray}-1.430 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$30.9 \mathrm{ms} \pm 284 \mathrm{μs}\left({\color{gray}1.03 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$30.7 \mathrm{ms} \pm 380 \mathrm{μs}\left({\color{gray}1.60 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.68 \mathrm{ms} \pm 44.2 \mathrm{μs}\left({\color{gray}0.823 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$88.5 \mathrm{ms} \pm 397 \mathrm{μs}\left({\color{gray}0.532 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$141 \mathrm{ms} \pm 542 \mathrm{μs}\left({\color{gray}0.345 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$95.5 \mathrm{ms} \pm 437 \mathrm{μs}\left({\color{gray}0.475 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$104 \mathrm{ms} \pm 467 \mathrm{μs}\left({\color{gray}0.077 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$113 \mathrm{ms} \pm 462 \mathrm{μs}\left({\color{gray}0.205 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$120 \mathrm{ms} \pm 496 \mathrm{μs}\left({\color{gray}0.239 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$86.2 \mathrm{ms} \pm 429 \mathrm{μs}\left({\color{gray}-0.170 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$114 \mathrm{ms} \pm 480 \mathrm{μs}\left({\color{gray}0.067 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$92.9 \mathrm{ms} \pm 392 \mathrm{μs}\left({\color{gray}-0.583 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$102 \mathrm{ms} \pm 385 \mathrm{μs}\left({\color{gray}-0.157 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$104 \mathrm{ms} \pm 457 \mathrm{μs}\left({\color{gray}0.514 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$104 \mathrm{ms} \pm 475 \mathrm{μs}\left({\color{gray}0.272 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$132 \mathrm{ms} \pm 488 \mathrm{μs}\left({\color{gray}-4.210 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$134 \mathrm{ms} \pm 573 \mathrm{μs}\left({\color{gray}-0.659 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$106 \mathrm{ms} \pm 793 \mathrm{μs}\left({\color{red}7.44 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$611 \mathrm{ms} \pm 3.59 \mathrm{ms}\left({\color{red}5.71 \mathrm{\%}}\right) $$ Flame Graph

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Base automatically changed from bm/be-434-hashql-entity-path-resolution-and-storage-mapping to main March 10, 2026 20:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > backend Owned by the @backend team

Development

Successfully merging this pull request may close these issues.

1 participant