Skip to main content

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:

ModeBehavior
autoKeep small supported work inline and move sufficiently large supported sorts to an isolate when beneficial
inlineExecute on the current isolate
isolateUse 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.