Performance Guidelines
FDC supports both local in-memory workflows and adapter-backed query workflows. Performance tuning starts by choosing the correct data path for the size and behavior of the application.
Keep small data local
For small and moderate local collections, use a memory-backed dataset and let filtering, sorting, searching, and aggregates run locally. This keeps the architecture simple and avoids unnecessary request overhead.
Use adapter-backed paging for large sources
For large tables or remote APIs, use paging and advertise only the adapter capabilities that the backend can execute correctly.
paging: const FdcDataPagingOptions(
enabled: true,
pageSize: 100,
requireTotalCount: true,
),
Use infinite mode when the UX should append sequential pages instead of replacing the current page.
Push query work to the source
With adapter-backed paging, filtering, sorting, searching, and aggregates should be executed by the adapter or backend when the capability is enabled. Avoid loading a very large source only to filter it in the UI process.
Tune large local DataSet operations
FdcDataSetOperationOptions controls how expensive local dataset work is executed. These options belong to the dataset layer, not the grid.
final dataSet = FdcDataSet(
fields: fields,
operationOptions: const FdcDataSetOperationOptions(
sortExecutionMode: FdcDataSetOperationExecutionMode.auto,
isolateSortThreshold: 100000,
cooperativeChunkSize: 8192,
enableSortValueCache: true,
sortValueCacheSize: 2,
),
);
Sort execution mode
FdcDataSetOperationExecutionMode supports:
| Mode | Behavior |
|---|---|
auto | Keep small supported work inline and move sufficiently large supported sorts to an isolate when beneficial |
inline | Execute on the current isolate |
isolate | Use a worker isolate when that operation supports isolate execution |
auto is the normal production choice. Force inline for deterministic diagnostics or environments where isolate transfer overhead would dominate. Force isolate only after measuring the actual workload.
Isolate threshold
isolateSortThreshold: 100000
The automatic policy considers isolate sorting only when the active view is large enough to cross this threshold. Lower is not automatically better: moving data and work to another isolate has overhead.
Cooperative chunk size
cooperativeChunkSize: 8192
Supported asynchronous local operations can yield cooperatively between chunks. Smaller chunks can improve UI responsiveness but increase scheduling overhead; larger chunks reduce handoff overhead but can create longer uninterrupted work intervals.
Sort value cache
enableSortValueCache: true,
sortValueCacheSize: 2,
The sort cache retains normalized values/ranks for a small number of fields. This helps repeated ascending/descending toggles and repeated sorts on expensive value representations.
Keep the cache intentionally small for very large datasets because normalized rank/value arrays consume memory proportional to row count.
See Work and Progress for observing long-running dataset operations.
Keep cell builders lightweight
Custom grid cell builders are called frequently while the viewport changes. Avoid expensive synchronous work, I/O, or object graphs that could have been prepared before rendering.
Prefer small immutable value objects and stable column configuration.
Avoid unnecessary dataset churn
Reuse a dataset instance for one logical data source instead of repeatedly constructing it during widget rebuilds. Open or reload intentionally, and dispose datasets when their owning application scope ends.
Treat aggregates as query work
For paged data, use adapter-backed aggregates rather than calculating totals only from the currently loaded page. Cache invalidation and refresh policy should follow actual data changes, not unrelated UI interactions.
Profile real workflows
Measure the behavior that matters in the application:
- first open;
- filtered query latency;
- page navigation;
- incremental infinite loading;
- edit/post/apply latency;
- large-grid scroll behavior;
- expensive custom cells.
Optimize after measuring the real path. A small local dataset and a million-row SQLite table need different strategies.