Performance
This document explains the performance characteristics and optimization strategies of Svelte DataGrid.
Performance Targets
| Operation | Target |
|---|---|
| UI updates | <16ms (60fps) |
| Sort 100K rows | <100ms |
| Filter 100K rows | <50ms |
| Scroll frame | <5ms |
Key Optimizations
1. Row Virtualization
Only visible rows are rendered. See Virtualization.
10,000 rows → ~25 DOM nodes
100,000 rows → ~25 DOM nodes DOM complexity stays constant regardless of data size.
2. Derived Memoization
Svelte 5’s $derived automatically memoizes computed values:
const sortedData = $derived(
sortData(data, currentSort)
); - Only recomputes when
dataorcurrentSortchanges - Cached between renders
- No manual memoization needed
3. Granular Reactivity
State is split into independent pieces:
let selectedRows = $state(new Set());
let currentSort = $state([]);
let filters = $state(new Map()); Changing selection doesn’t trigger sort recomputation.
4. Batched Updates
Multiple state changes are batched:
function resetFilters() {
filters.clear();
globalSearchTerm = '';
// Svelte batches into single update
} 5. Efficient Array Operations
We use efficient algorithms:
// O(n log n) sort with stable comparison
const sorted = [...data].sort(compareFn);
// O(n) filter with early termination
const filtered = data.filter(predicateFn); Measuring Performance
Browser DevTools
// Measure sort time
console.time('sort');
gridState.setSort([{ field: 'name', direction: 'asc' }]);
await gridState.waitForData();
console.timeEnd('sort'); Performance API
const start = performance.now();
// operation
const end = performance.now();
console.log(`Operation took ${end - start}ms`); Best Practices
1. Provide getRowId
Always provide getRowId for stable row identification:
<DataGrid
{data}
{columns}
getRowId={(row) => row.id}
/> Without it, selection breaks when data is sorted/filtered.
2. Avoid Heavy Render Functions
Keep cell render functions simple:
// Good: simple formatting
render: (value) => `$${value.toFixed(2)}`
// Bad: complex computation
render: (value, row) => expensiveCalculation(row) 3. Use Appropriate DataSource
- Under 10K rows: LocalDataSource is fine
- 10K-100K rows: Consider server-side pagination
- Over 100K rows: Use server-side operations
<!-- For large datasets -->
<DataGrid
dataSource={serverDataSource}
{columns}
/> 4. Limit Visible Columns
More columns = more cells to render:
const columns = [
// Show only essential columns
{ key: 'id', header: 'ID' },
{ key: 'name', header: 'Name' },
// Hide less important columns initially
{ key: 'details', header: 'Details', visible: false }
]; 5. Debounce User Input
Filters and search are debounced by default (300ms). For custom inputs:
import { debounce } from '$lib/utils';
const debouncedFilter = debounce((value) => {
gridState.setFilter('name', value);
}, 300); Common Performance Issues
Slow Initial Render
Cause: Too many columns or complex cell renderers.
Fix:
- Reduce visible columns
- Simplify render functions
- Use virtualization (enabled by default)
Janky Scrolling
Cause: Too few overscan rows or expensive cell renders.
Fix:
- Increase
overscanprop (default: 5) - Simplify cell content
- Use CSS instead of inline styles
Slow Sorting
Cause: Large dataset with client-side sort.
Fix:
- Use server-side sorting
- Implement pagination
- Consider indexing data
Memory Usage
Cause: Storing full dataset in memory.
Fix:
- Use pagination with server-side data
- Implement lazy loading
- Consider windowing for very large datasets
Benchmarks
Tested on MacBook Pro M1, Chrome 120:
| Operation | 1K rows | 10K rows | 100K rows |
|---|---|---|---|
| Initial render | 8ms | 12ms | 15ms |
| Sort (client) | 2ms | 18ms | 85ms |
| Filter (client) | 1ms | 8ms | 42ms |
| Scroll frame | 2ms | 2ms | 2ms |
| Select all | 3ms | 25ms | 240ms |
Key insight: scroll performance is constant because of virtualization.
Profiling Tips
React DevTools (Svelte 5)
Use browser profiler to identify slow components:
- Open DevTools → Performance tab
- Start recording
- Perform action (sort, filter, scroll)
- Stop recording
- Look for long tasks
Identify Re-renders
Add logging to track renders:
<script>
$effect(() => {
console.log('Component re-rendered');
});
</script> See also
- Virtualization - Row virtualization details
- State Management - Reactive state optimization
- Reference: DataGrid - Performance-related props