Change 3 of issue 0133 — rewire compute_visible_rows, filter eval,
and sort comparators to read from the SnapshotCache when available.
Hot paths rewired:
- compute_visible_rows (overload with snap): filter eval uses
compare_snap (fast i64/f64 numeric compare for Int/Float cols;
id-compare for low-cardinality string Eq/Neq; raw cells fallback
for Contains/StartsWith/EndsWith).
- Sort comparators: direct i64/f64 array compare for Int/Float cols
(goto sort_done skips string fallback); string sort uses uint32_t
id compare with pool lookup only on mismatch.
- Stage>0 filter/sort: same snapshot overload.
Materialization paths (build_so, s0_backing, mat_backing, config popup)
kept on raw cells — they copy into std::string anyway, no benefit from
snapshot and snprintf-per-cell was 2M extra calls per frame.
Bug fixes (required for correctness):
1. StringPool::intern() realloc safety: force reserve before
emplace_back so string_view keys in the map never go dangling.
2. SnapshotCache::pool_size_built sentinel: detects when a new State
is created with an empty pool but same cells pointer (begin_scenario
pattern). Prevents str_ids from indexing into an empty pool (SIGSEGV).
3. Cardinality cap (2048 uniques / 25% sample): high-cardinality string
cols (timestamps-as-strings, UUIDs, names) skip interning — str_ids
stays empty and compare_snap falls back to raw cells. Prevents 30MB+
pool bloat that hurt cache for filter/sort on other cols.
Bench delta vs baseline (100k rows, LIBGL_ALWAYS_SOFTWARE=1):
linear_scroll: 16.0 -> 15.5 fps p50 (-3%, baseline already FAIL)
filter_like: 59.7 -> 56.0 fps p50 (-6%, still PASS at 56fps)
sort_numeric: 3.9 -> 9.0 fps p50 (+131%, snapshot i64 sort)
color_rule: 15.2 -> 14.8 fps p50 (-3%, baseline already FAIL)
Build: green for all 10 available Linux consumers (text_editor_smoke
linker failure is preexisting, not caused by this change).
API public intact. TableEvent.row indexing TableInput preserved.
Pointer-identity invalidation preserved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Change 1 — Columnar Snapshot Internal:
- Add ColumnSnapshot struct (type + str_ids/i64/f64 per column) in data_table_internal.h
- Add SnapshotCache struct with pointer-identity sentinel (last_cells_ptr)
- Add SnapshotCache field to UiState singleton
- In render(): rebuild snapshot after join materialization when cells ptr changes
Uses same pointer-identity pattern as existing stats_last_cells in State
Int/Float columns parsed once via parse_number; String/Auto interned
Change 2 — String Interning:
- Add StringPool struct (strings + unordered_map<string_view, uint32_t>) to data_table_types.h
- StringPool is per-State (NOT global) for table isolation
- intern(sv) inserts if absent, returns stable uint32_t index
- Cleared + rebuilt on each snapshot rebuild for index coherence
- Add string_pool field to State struct
Documentation:
- Extended header comment in data_table_internal.h describing design,
StringPool API, invariants (pointer-identity, row→snapshot_row),
and how stats_last_cells and snapshot coexist independently
Build: fn_module_data_table + tables_qa pass, no new errors (only
pre-existing -Wformat-truncation warnings unrelated to this change).
Public API (data_table.h, TableInput, render() signature) unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Snapshot de WIP acumulado de sesiones previas antes de merge wave 1
del flow 0008 (kanban_cpp + agent_runner_api + DoD schema).
Incluye:
- dev/flows/0008-kanban-cpp-and-agent-workflows.md
- dev/issues/0112-0119*.md (7 sub-issues)
- WIP previo en cmd/fn/doctor.go, registry/*, modules/, cpp/, etc.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>