Performance
Performance
Section titled “Performance”Optimize grid performance for large datasets and high-frequency updates.
Virtualization
Section titled “Virtualization”The grid automatically virtualizes when row count exceeds 100.
How It Works
Section titled “How It Works”- Only visible rows are rendered to the DOM
- Scroll position determines which rows to show
- Buffer rows above/below viewport for smooth scrolling
Manual Control
Section titled “Manual Control”// Always virtualize (even small datasets)<DataGrid virtualize={true} ... />
// Never virtualize<DataGrid virtualize={false} ... />
// Auto (default) - virtualize when rows > 100<DataGrid virtualize="auto" ... />Custom Row Height
Section titled “Custom Row Height”For accurate virtualization, specify row height:
<DataGrid rowHeight={32} // Default: 36 .../>WASM Acceleration
Section titled “WASM Acceleration”Install the optional WASM core for maximum performance:
npm install @askturret/grid-wasmWhat WASM Accelerates
Section titled “What WASM Accelerates”| Operation | JavaScript | WASM |
|---|---|---|
| Sort 100k rows | ~180ms | 5ms |
| Filter 100k rows | ~80ms | <1ms |
| Aggregations | ~100ms | 10ms |
Automatic Detection
Section titled “Automatic Detection”The grid automatically uses WASM when available:
// No code changes needed// Grid detects and uses WASM core if installedManual Initialization
Section titled “Manual Initialization”For explicit control:
import { initWasm } from '@askturret/grid';
// Initialize WASM early (e.g., app startup)await initWasm();Flash Highlighting
Section titled “Flash Highlighting”Lazy Detection
Section titled “Lazy Detection”Flash detection only runs for visible rows, not the entire dataset.
Adaptive Mode
Section titled “Adaptive Mode”Flash effects automatically disable when FPS drops:
- Disables at 55 FPS
- Re-enables at 58 FPS
- Prevents performance degradation during heavy updates
Disable Flash
Section titled “Disable Flash”For maximum performance:
<DataGrid disableFlash ... />Benchmarks
Section titled “Benchmarks”Tested on AMD Ryzen, Linux, Chrome 131:
Initial Render
Section titled “Initial Render”| Row Count | Render Time |
|---|---|
| 1,000 | 12ms |
| 10,000 | 45ms |
| 100,000 | 52ms |
| 1,000,000 | 68ms |
Sort Performance (WASM)
Section titled “Sort Performance (WASM)”| Row Count | Sort Time |
|---|---|
| 10,000 | 2ms |
| 100,000 | 5ms |
| 1,000,000 | 18ms |
Filter Performance (Trigram Index)
Section titled “Filter Performance (Trigram Index)”| Row Count | Filter Time |
|---|---|
| 10,000 | <1ms |
| 100,000 | <1ms |
| 1,000,000 | <2ms |
Update Performance
Section titled “Update Performance”| Update Rate | FPS Maintained |
|---|---|
| 100 rows/sec | 60 FPS |
| 1,000 rows/sec | 60 FPS |
| 10,000 rows/sec | 55+ FPS |
Best Practices
Section titled “Best Practices”1. Use Stable Row Keys
Section titled “1. Use Stable Row Keys”// Good - stable, unique key<DataGrid rowKey="id" ... />
// Bad - index as key (breaks optimization)<DataGrid rowKey={(row, index) => index} ... />2. Memoize Column Definitions
Section titled “2. Memoize Column Definitions”// Good - columns don't change referenceconst columns = useMemo(() => [ { field: 'name', header: 'Name' }, { field: 'price', header: 'Price' },], []);
// Bad - new array every render<DataGrid columns={[ { field: 'name', header: 'Name' },]} ... />3. Batch Updates
Section titled “3. Batch Updates”// Good - single state updatesetData(prev => { const updated = [...prev]; updates.forEach(update => { const index = updated.findIndex(r => r.id === update.id); if (index >= 0) updated[index] = { ...updated[index], ...update }; }); return updated;});
// Bad - multiple state updatesupdates.forEach(update => { setData(prev => prev.map(r => r.id === update.id ? { ...r, ...update } : r ));});4. Use Immutable Updates
Section titled “4. Use Immutable Updates”// Good - new object referencesetData(prev => prev.map(row => row.id === id ? { ...row, price: newPrice } : row));
// Bad - mutationdata.find(r => r.id === id).price = newPrice;setData([...data]);5. Throttle High-Frequency Updates
Section titled “5. Throttle High-Frequency Updates”import { throttle } from 'lodash';
const updateData = throttle((updates) => { setData(prev => applyUpdates(prev, updates));}, 100); // Max 10 updates per second6. Pre-Filter Data
Section titled “6. Pre-Filter Data”For complex filters, filter before passing to grid:
const filteredData = useMemo(() => { return allData.filter(row => { // Complex filter logic return row.status === status && row.price > minPrice; });}, [allData, status, minPrice]);
<DataGrid data={filteredData} ... />Memory Usage
Section titled “Memory Usage”Typical Memory Footprint
Section titled “Typical Memory Footprint”| Row Count | Memory Usage |
|---|---|
| 10,000 | ~15 MB |
| 100,000 | ~80 MB |
| 1,000,000 | ~400 MB |
Optimization Tips
Section titled “Optimization Tips”- Limit columns: Only include necessary fields
- Use compact mode: Smaller row height = less DOM
- Paginate if needed: For 1M+ rows, consider pagination
Profiling
Section titled “Profiling”React DevTools
Section titled “React DevTools”- Open React DevTools Profiler
- Record during interaction
- Look for unnecessary re-renders
Performance API
Section titled “Performance API”// Measure sort timeperformance.mark('sort-start');// ... sort operationperformance.mark('sort-end');performance.measure('sort', 'sort-start', 'sort-end');
const measure = performance.getEntriesByName('sort')[0];console.log(`Sort took ${measure.duration}ms`);FPS Monitor
Section titled “FPS Monitor”The grid includes an internal FPS monitor for adaptive mode. Access it for debugging:
import { useAdaptiveFlash } from '@askturret/grid';
function DebugPanel() { const { enabled, fps } = useAdaptiveFlash(); return <div>FPS: {fps}, Flash: {enabled ? 'on' : 'off'}</div>;}