Skip to content

perf(gfql): materialize indexed point-query rows directly - #2072

Merged
lmeyerov merged 42 commits into
masterfrom
perf/gfql-indexed-point-rows
Sep 13, 2026
Merged

perf(gfql): materialize indexed point-query rows directly#2072
lmeyerov merged 42 commits into
masterfrom
perf/gfql-indexed-point-rows

Conversation

@lmeyerov

@lmeyerov lmeyerov commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Scalar node and directed one-hop queries ending in rows(...) construct traversal results and evaluate expressions for very small outputs. This change gathers matching rows through resident indexes and projects them directly on pandas, cuDF, and CPU Polars. Joined projections retain one result per matching edge, including repeated matches.

The routes preserve row and column order, dtypes, aliases, empty schemas, graph metadata, validation, and unsupported-query fallback. Polars avoids redundant singleton operations, schema inspection, and validation. Supported equality filters on two to 32 eager Polars rows avoid expression plans; CPU Polars gathers of two to eight rows use slices, with scattered gathers limited to 32 columns. Larger and unsupported cases retain the generic path. Valid property indexes can be reused across CPU and GPU execution targets while retaining frame identity and fingerprint checks.

Review hardening includes:

  • Shared identifier/expression parsers, narrower scalar/index/backend types, and removal of join type suppressions.
  • Immediate Chain validation plus execution checks for mutation, reuse, custom validators, and error ordering.
  • Native and generic path ordering, physical duplicate/null rows and supplied starting wavefronts, and HAS-label collision disambiguation before filtering/deduplication.
  • Exact nullable Int64/UInt64 identifiers above 2^53, alias-property restoration through entity identity, and consistent empty-edge schemas/bindings.
  • Independent boundary/generalization assertions, with result checks active when routes are disabled and engagement checks scoped to their actual engine/shape. Existing suites replay through all nine individual registered routes plus all-off; CI requires every replay to pass and guards against missing modes.

Current published head: b5703a35c70b3176e4d815adac04bc1bc9252870. Real-fixture phase probes on both preceding revisions identified variable one-row projection costs in Polars expression collection (roughly 0.12–0.32 ms). This repair builds resolved Cypher property columns directly from their Series. General Polars projection also gathers direct columns and short-circuits coalesce when matching dtypes and null counts prove the chosen column; mixed-null, mixed-type, and unsupported expression cases retain the generic path. Existing expression lowering, temporal checks, row cardinality, and source isolation remain in force.

The repair adds 64 cases to the existing Polars row-pipeline suite, covering empty/single/larger frames, integer precision, null boundaries, NaN, repeated columns, and categorical/enum/list/struct dtypes. The final focused suite passed 323 tests; broader point/boundary/latency integration passed 697 tests including actual cuDF. Full lint and typing for both changed source files passed. The total review addition is now 641 collected parameterized product cases, not independent bugs or additive execution passes.

Validation on this published revision:

  • Product CI: all 85 jobs passed. All nine individual route replays plus all-off report zero divergences. All-off: 12,631 passed, 3,030 skipped, 405 expected failures, two non-strict unexpected passes.
  • Full DGX compute plus JSON validation: 17,975 passed, 110 skipped, 102 expected failures, 14 non-strict unexpected passes, and two subtests in 501.74 seconds. Official RAPIDS 26.02, cuDF 26.02.01, Polars 1.35.2; CuPy compute and actual Polars GPU collection preflights passed. Transferred source hash and successful guarded runner/workload completion were verified.
  • pyg-bench candidate: 53 mandatory checks passed, no skips.
  • TCK main: 4,169 passed/six skipped/689 expected failures in each normal/all-nine-off mode.
  • TCK PR199: 4,329 passed/86 skipped/689 expected failures in each mode. PR199 adds 240 regression cases for alias identity, nullable identifiers, path order, node selection, and HAS collisions. All candidate logs verify the exact product SHA.

The final latency sentinel passed unchanged absolute and 1.5× historical-baseline drift gates, including correctness, index engagement, and expected fallback. Eight native Polars shapes measured 0.120–0.281 ms against the 0.7 ms limit. IS5 measured 0.192 ms, seeded-hop properties 0.187 ms, and native coalesce 0.165 ms. The alias-collision fallback returned correct results at 23.525 ms. Sampling: eight warmups and 63 measurements.

Broader measurements use product b5703a35c70b3176e4d815adac04bc1bc9252870 and frozen harness 557665417a8a5f6f0024b5500e1f9997729d37fe on DGX Spark. All 12 current Polars/pandas runs and 18 retained matched competitor runs passed source, dataset, sampling, resource, and result validation. Competitor runs come from the earlier H557 campaign; they were not rerun with this product change. Every shared expected and actual result hash matches. Sampling: eight warmups, 31 measurements, three independent runs; timings include execution and full record materialization. Tables show median-of-run-medians in milliseconds. A dash means not measured. These are internal SNB-derived results, not official LDBC results.

SF0.1:

Query Polars Kuzu Neo4j Memgraph
seed-lookup 1.071 2.404 3.212 0.638
message-content 0.171 0.648 1.838 0.373
message-creator 0.250 1.501 1.906 0.458
message-replies 9.370 24.287
new-topics 42.621 48.958
recent-replies 28.736 32.008 5.431 3.954

SF1:

Query Polars Kuzu Neo4j Memgraph
seed-lookup 1.462 2.084 3.420 0.509
message-content 0.173 0.688 2.102 0.432
message-creator 0.247 1.778 2.021 0.452
new-topics 169.694 210.852

Polars leads Kuzu in all ten eligible comparisons. It leads Neo4j on all six point-query comparisons; Neo4j is faster on SF0.1 recent replies. Polars leads Memgraph on message content and creator at both scales; Memgraph is faster on seed lookup at both scales and SF0.1 recent replies. The ±10% ratio band is a reporting convention, not a statistical significance test; SF0.1 recent replies versus Kuzu is close to the boundary. Relative to the original product73565 run medians, message content improved from 0.417→0.171 ms at SF0.1 and 0.762→0.173 ms at SF1; creator improved from 0.513→0.250 ms and 0.708→0.247 ms. Seed lookup increased about 9% at each scale; other measured larger-query changes range from approximately −1% to +7%.

SF0.1 tag cooccurrence is excluded because its selected parameter returns zero rows. SF1 message replies and recent replies were not measured for Polars. Memgraph used a 4 GiB container/3072 MiB engine cap at SF0.1 and a 16 GiB container/12288 MiB engine cap at SF1, consistent across repetitions. The initial failed SF1 import with the smaller engine cap is retained and excluded.

Separate instrumented GPU/index probes passed all seven SF0.1 and four SF1 result checks on the final product revision. GPU collect calls were observed in five SF0.1 queries and two SF1 queries. Message content and creator used eager CPU paths despite the requested GPU target. Seed lookup, message content, and creator all engaged the property index at both scales. A GPU configuration label does not establish GPU execution for every operation. All instrumented timings are excluded from the comparison tables.

Earlier642be latency runs failed relative drift checks. All failures and alternating-pair/phase diagnostics were retained; phase evidence motivated the current direct-projection repair. Current b570 passed the original gates without threshold relaxation. Historical receipts retain their original revision labels.

The harness has correctness/index/route pins and a candidate latency profile requiring all eight native Polars shapes at or below 0.7 ms plus the expected collision fallback. Candidate checks fail on missing or skipped mandatory tests. pyg-bench PR260 adds automatic enforcement when configured. After product merge, actual-master baselines, measured pandas median×1.5 bounds, release configuration activation, and dependent TCK199 validation/merge remain required. They do not use a candidate result relabeled as master.

Colleague-owned aggregation execution/validation and whole-entity metadata work is tracked in issue2074. Integration must preserve both sets of correctness expectations. Docs2017 follows the product and benchmark release gates.

An isolated merge of this head with current master 24233cb701e4757d9d6d71c9c0394ce9d4393351 is conflict-free. The combined tree passed 697 focused product tests (one skip; 64 Polars-GPU cases deselected locally) and all 240 TCK199 regressions with pandas, Polars, and cuDF enabled. This is local integration evidence; actual merged-master GPU and baseline validation still follows owner merge.

@lmeyerov
lmeyerov changed the base branch from perf/gfql-native-seed-skip-refilter to master September 12, 2026 17:49
Comment thread graphistry/compute/chain_specializations/admission.py Outdated
Comment thread graphistry/compute/chain_specializations/point_rows.py Outdated
Comment thread graphistry/compute/chain_specializations/point_rows.py Outdated
Comment thread graphistry/compute/dataframe/join.py
Comment thread graphistry/compute/chain.py Outdated
Comment thread graphistry/tests/compute/gfql/routes/corpus.py
@lmeyerov
lmeyerov marked this pull request as ready for review September 13, 2026 01:33
@lmeyerov
lmeyerov merged commit 2ca9892 into master Sep 13, 2026
90 checks passed
@lmeyerov
lmeyerov deleted the perf/gfql-indexed-point-rows branch September 13, 2026 02:34
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.

1 participant