Skip to content

perf(gfql): route engine=auto to native polars for polars-frame graphs#1743

Draft
lmeyerov wants to merge 3 commits into
masterfrom
fix/gfql-auto-engine-polars-native
Draft

perf(gfql): route engine=auto to native polars for polars-frame graphs#1743
lmeyerov wants to merge 3 commits into
masterfrom
fix/gfql-auto-engine-polars-native

Conversation

@lmeyerov

Copy link
Copy Markdown
Contributor

Summary

resolve_engine(AUTO) maps polars frames to Engine.PANDAS (that branch predates Engine.POLARS), so g.gfql(query) on a polars-frame graph silently bridges to the generic pandas path — measured ~3× on a small seeded cypher query and ~13× on the q5 graph-benchmark shape (see plans/gfql-benchmark-numbers), with pandas frames coming back out.

This routes engine='auto' (the default) to the native polars engine when both bound frames are polars, with an honest-NotImplementedError fallback to the legacy AUTO path — the fallback is permitted here because the user did not pin an engine (the no-silent-fallback contract applies to explicit engine=).

  • Scope is deliberately gfql-only (one guard in gfql()): changing resolve_engine itself would ripple into plotting/util paths that only handle pandas/cudf.
  • Behavior change: AUTO results on polars graphs are now polars frames (frames in = frames out) and previously-bridged queries now run natively; polars-NIE shapes (e.g. shortestPath) still answer via the fallback (test-pinned).

Measurements (2k-node polars graph, seeded 1-hop cypher, warm)

engine before after
'polars' (explicit) 8.5ms / polars out 8.8ms / polars out
default (auto) 25.0ms / pandas out 9.3ms / polars out

Tests

  • TestAutoEngineRoutesPolarsNative: auto == explicit-polars result (frame-equal, native frames); shortestPath NIEs when pinned but answers via auto fallback.
  • Full polars lanes: 1224 passed (1 pre-existing dask env failure, fails on master too).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL

lmeyerov and others added 3 commits July 19, 2026 23:47
resolve_engine(AUTO) maps polars frames to PANDAS (it predates
Engine.POLARS), so g.gfql(query) on a polars-frame graph silently
bridged to the generic pandas path: ~3-13x slower on cypher point
queries and pandas frames out. Route AUTO to the native polars engine;
an honest NotImplementedError (unsupported shape) falls back to the
legacy AUTO path — allowed because the user did not pin an engine.
Frames in = frames out: AUTO results on polars graphs are now polars.

Repro: 2k-node polars graph, seeded 1-hop cypher — AUTO 25.0ms/pandas
out before, 9.3ms/polars out after (engine='polars' = 8.8ms); polars-NIE
shapes (shortestPath) still answer via the pandas fallback.

Fixes the q5 finding in plans/gfql-benchmark-numbers (inferred-engine
13x penalty).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
…c records

The dual-path guards checked hasattr(out, 'to_dict') first, but polars
DataFrame HAS to_dict (without orient) — so the polars branch was
unreachable and these tests only ever ran because auto silently returned
pandas. With auto routing polars-frame graphs natively they now receive
polars frames; probe to_dicts first. Assertions (record values) unchanged
and still pass on both engines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
@lmeyerov

Copy link
Copy Markdown
Contributor Author

Too early to enable by default

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