Skip to content

perf(gfql): generalize seeded typed-hop fast path to polars/polars-gpu (#1755)#1760

Merged
lmeyerov merged 5 commits into
masterfrom
perf/gfql-seeded-fastpath-polars-1755
Jul 21, 2026
Merged

perf(gfql): generalize seeded typed-hop fast path to polars/polars-gpu (#1755)#1760
lmeyerov merged 5 commits into
masterfrom
perf/gfql-seeded-fastpath-polars-1755

Conversation

@lmeyerov

Copy link
Copy Markdown
Contributor

Stacked on #1759 (base = perf/gfql-seeded-typed-hop-fastpath-1755). Review/merge #1759 first.

What

Generalizes the #1755 seeded typed-hop cypher fast path (pandas-only in #1759)
to polars and polars-gpu via _seeded_typed_return_dst_polars — the same
seed-first reduction (seed out-edges → typed-edge filter → destination nodes)
expressed with polars filters. It hooks upstream at
_execute_seeded_typed_hop_fast_path, before the lazy pipeline, so none of the
woven binding_rows_polars / hop_polars / combine machinery changes.

dgx measurement (26.02-gfql-polars, 50k Person / 200k Message, warm median)

MATCH (m:Message {id})-[:HAS_CREATOR]->(p:Person) RETURN p:

engine full fast speedup parity
pandas 40.6 ms 2.0 ms 20.3×
polars 13.7 ms 3.44 ms 4.0×
polars-gpu 24.6 ms 2.47 ms 10.0×
cudf 27.8 ms (falls through) 1.0×

The fast path now engages on pandas/polars/polars-gpu; cuDF falls through (the
generic chain fast path already helps it).

Correctness

  • Dispatch keys off the actual frame type (is_polars_df), not the requested
    engine — the WITH..MATCH reentry path can request engine=polars while handing
    a pandas-materialized intermediate graph, which would otherwise run polars ops
    on a pandas frame. (Caught by test_with_match_reentry_differential_fuzz.)
  • Differential parity (fast vs full) byte-identical on polars, plus an
    independent oracle (hand-computed creators) and varlen-decline coverage.
  • Zero non-seeded regressions: full compute/gfql + test_chain suite = 77
    failed / 5096 passed vs perf(gfql): seeded typed-hop fast path — seeded 1-hop RETURN in ≤1ms (#1755) #1759 baseline 77 / 5090 (identical failure set — all
    pre-existing local polars-drift/GPU-lib), +6 net new passing tests.
  • mypy clean on both changed source files.

🤖 Generated with Claude Code

@lmeyerov
lmeyerov force-pushed the perf/gfql-seeded-fastpath-polars-1755 branch from 6c4440d to e547753 Compare July 21, 2026 19:13
@lmeyerov
lmeyerov force-pushed the perf/gfql-seeded-typed-hop-fastpath-1755 branch from 855123a to dec4e4a Compare July 21, 2026 20:57
@lmeyerov
lmeyerov force-pushed the perf/gfql-seeded-fastpath-polars-1755 branch from e547753 to dadb1bd Compare July 21, 2026 20:57
@lmeyerov

Copy link
Copy Markdown
Contributor Author

Review responses:

lmeyerov and others added 3 commits July 21, 2026 14:24
#1755)

Extends the seeded cypher RETURN fast path (previously pandas-only) to
polars/polars-gpu via _seeded_typed_return_dst_polars — same seed-first
reduction (seed out-edges -> typed-edge filter -> destination nodes) expressed
with polars filters, hooking upstream at _execute_seeded_typed_hop_fast_path
before the lazy pipeline, so no change to the woven binding_rows/hop_polars.

Dispatch keys off the ACTUAL frame type (is_polars_df), not the requested
engine: the WITH..MATCH reentry path can request engine=polars while handing a
pandas-materialized intermediate graph, so trusting requested_engine would run
polars ops on a pandas frame. cuDF still falls through (generic chain fast path
already helps it).

Tests: TestCypherSeededTypedHopPolars (differential parity + independent oracle
+ engagement + varlen decline); fixes _canon_nodes to convert polars->pandas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
…1755)

Review response: direction param was str, now the Direction Literal
(matching the pandas/cudf helpers); add the missing CHANGELOG entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
…semantics (#1755)

Review-skill wave findings:
- LazyFrame-backed / mixed-engine node+edge graphs now DECLINE (was AttributeError
  mid-helper); dispatch also declines when node/edge frame families differ
- label__X resolution + typing unified on _seeded_scalar_filters (list-'labels'
  precedence, edge-frame rule; drops the loose Any closure)
- membership sets drop_nulls()'d + passed via .implode() (null ids never link;
  Series-arg is_in deprecated in polars 1.42, polars#22149)
- 4 regression tests (TestPolarsFastPathGates); suite passes with
  -W error::DeprecationWarning

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
@lmeyerov
lmeyerov force-pushed the perf/gfql-seeded-fastpath-polars-1755 branch from dadb1bd to 22cf378 Compare July 21, 2026 21:27
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
@lmeyerov
lmeyerov changed the base branch from perf/gfql-seeded-typed-hop-fastpath-1755 to master July 21, 2026 21:45
The polars seeded helper's lines are exercised only where polars is
installed; add the test file to POLARS_TEST_FILES so the combined
changed-line-coverage gate sees them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
@lmeyerov
lmeyerov merged commit 50a2df4 into master Jul 21, 2026
77 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.

1 participant