Skip to content

perf(grid): compile filter predicates once instead of per row (#1550) - #1611

Merged
ZhuchkaTriplesix merged 1 commit into
devfrom
issue/1550-compiled-predicates
Oct 15, 2026
Merged

ZhuchkaTriplesix merged 1 commit into
devfrom
issue/1550-compiled-predicates

Conversation

@ZhuchkaTriplesix

Copy link
Copy Markdown
Member

Summary

_PredicateNode.evaluate re-derived everything from the raw strings for every row: op.toUpperCase().trim(), targetValue.toLowerCase() and double.tryParse(targetValue) (the target never changes), the lower-cased and trimmed IN list on each row (O(rows x list)), and the BETWEEN bounds.

The constructor now resolves them once: _upperOp, _lowerTarget, _numTarget, _inSet (a Set<String> of normalised values) and _numMin / _numMax. evaluate is a switch on the resolved operator and only reads the cell. Semantics are as before: numeric comparison when both sides parse, otherwise case-insensitive string comparison; NULL / null / empty count as null; BETWEEN without both bounds falls through to the comparison path.

The only per-row string work left is on the cell side (toLowerCase, trim, tryParse of the cell), which cannot be hoisted.

This touches the node class only; the lexer changes in #1607 are in the same file but different lines.

Tests (not run locally; CI will)

test/features/workspace/grid_filter_predicate_test.dart: IN / NOT IN with mixed case and spaces, numeric and string BETWEEN, numeric vs string comparison (20.0 = 20, price = abc), : and != ignoring case, and IS NULL for NULL / null / empty.

The before / after timing on 50k rows asked for in the issue is not included; the harness is not in the repo.

Closes #1550

_PredicateNode.evaluate re-derived everything from the operator and operand
strings for every row: op.toUpperCase().trim(), targetValue.toLowerCase() and
double.tryParse(targetValue), the lower-cased and trimmed IN list (O(rows x
list)) and the BETWEEN bounds.

The constructor now computes the operator, the lower-cased target, its number,
the normalised IN set and the BETWEEN bounds once; evaluate only reads the
cell. Semantics are unchanged: numeric comparison when both sides parse,
otherwise case-insensitive string comparison, NULL / null / empty are null.

Closes #1550
@github-actions github-actions Bot added enhancement New feature or request performance Theme parser epic label: performance data-grid Interactive data grid, cell editor, filtering, groupings P3 Low priority / Polish & Enhancements labels Oct 15, 2026
@github-actions github-actions Bot added this to the 0.5.0 milestone Oct 15, 2026
@ZhuchkaTriplesix
ZhuchkaTriplesix merged commit 5072969 into dev Oct 15, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data-grid Interactive data grid, cell editor, filtering, groupings enhancement New feature or request P3 Low priority / Polish & Enhancements performance Theme parser epic label: performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant