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
searchAny / search_nodes / search_edges (WYSIWYG search, #1700) render each candidate column to its display string, then substring-match. Modeling interactive search (typing into a search box → a new query per keystroke over a fixed base graph / filtered view), the render dominates and is term-independent — so it should be materialized once as a search-text index, not recomputed per keystroke. This belongs with the manual/explicit CREATE INDEX work (#531, #1658), not as an implicit cache inside searchAny (statefulness + invalidation on data/format-option change is a footgun and would silently diverge).
Base vs view: slicing the base blob to a 50% filtered view = 8 ms slice + 36 ms keystroke — the index lives at the base-graph level and slices to the filtered/rendered view; no per-keystroke re-render.
Render-vs-match split @1m: datetime render = 8× a single match, float = 2.3×, int ≈ 1×, string ≈ free. (Contains itself is ~125–155 ms/column @1m — the irreducible per-column floor, which the blob collapses to one match.)
Recommendation
A search-text index (new index type under #531 / the CREATE INDEX stack): materialize one concatenated, lowercased WYSIWYG search-text column per (data, format-options), built once, sliced to the active view, so each keystroke is a single Contains. This is the 43× win — 1M-row interactive search goes ~3 s → ~68 ms/keystroke.
Design notes:
Key by (columns, float_precision, tz, temporal_format, case_sensitive); invalidate on data or option change (explicit CREATE INDEX sidesteps implicit-staleness).
Blob (single joined column) beats a per-column cache (68 ms vs 439 ms) because it's one Contains regardless of column count; keep a per-column variant if column-scoped columns= targeting must stay index-accelerated.
Placement is open: GFQL/Plottable-level explicit index vs the streamgl-viz worker that owns the interactive session lifecycle.
Already landed in #1700 (render speedups, byte-identical)
Float render: list-comp (the np.char.mod/masked-scatter was slower).
Datetime render: vectorized .dt-component assembly for the default+UTC case (pandas dt.strftime is ~20× slower, ~2.2 s/1M); strftime retained for custom format / non-UTC tz.
Interactive + index-prototype benchmarks over a 100K/1M mixed-column table (string/int/float/datetime/bool), rendering each column via graphistry.compute.gfql.search_any._canonical_float_str / _canonical_datetime_str; blob = Series.str.cat(sep="\x00") of the lowercased renders; view = blob.loc[filtered_index]. Run on dgx image graphistry/test-rapids-official:26.02-gfql.
Summary
searchAny/search_nodes/search_edges(WYSIWYG search, #1700) render each candidate column to its display string, then substring-match. Modeling interactive search (typing into a search box → a new query per keystroke over a fixed base graph / filtered view), the render dominates and is term-independent — so it should be materialized once as a search-text index, not recomputed per keystroke. This belongs with the manual/explicitCREATE INDEXwork (#531, #1658), not as an implicit cache insidesearchAny(statefulness + invalidation on data/format-option change is a footgun and would silently diverge).Findings (dgx-spark, pandas, 1M rows, 8 mixed-typed columns)
Per-keystroke latency for a 4-char type-in, auto-searching all eligible columns:
Contains(OR)ContainsRecommendation
A search-text index (new index type under #531 / the
CREATE INDEXstack): materialize one concatenated, lowercased WYSIWYG search-text column per (data, format-options), built once, sliced to the active view, so each keystroke is a singleContains. This is the 43× win — 1M-row interactive search goes ~3 s → ~68 ms/keystroke.Design notes:
float_precision,tz,temporal_format,case_sensitive); invalidate on data or option change (explicitCREATE INDEXsidesteps implicit-staleness).Containsregardless of column count; keep a per-column variant if column-scopedcolumns=targeting must stay index-accelerated.Plottable-level explicit index vs the streamgl-viz worker that owns the interactive session lifecycle.Already landed in #1700 (render speedups, byte-identical)
np.char.mod/masked-scatter was slower)..dt-component assembly for the default+UTC case (pandasdt.strftimeis ~20× slower, ~2.2 s/1M); strftime retained for custom format / non-UTC tz.Repro
Interactive + index-prototype benchmarks over a 100K/1M mixed-column table (string/int/float/datetime/bool), rendering each column via
graphistry.compute.gfql.search_any._canonical_float_str/_canonical_datetime_str; blob =Series.str.cat(sep="\x00")of the lowercased renders; view =blob.loc[filtered_index]. Run on dgx imagegraphistry/test-rapids-official:26.02-gfql.Refs: #1700 (WYSIWYG searchAny), #531 (GFQL indexing), #1658 / #1697 / #1676 (index stack).