Skip to content

Performance & Isolates

Fasq includes built-in tools to keep your application frame-perfect, even when dealing with heavy data parsing or transformations.

Parsing large JSON responses on the main thread can cause UI jank. Fasq provides a managed IsolatePool to offload these tasks effortlessly.

[!NOTE] Fasq does not automatically run your queryFn in an isolate. Networking and basic async operations are already non-blocking in Dart. Isolates are only needed for CPU-intensive work like parsing large JSON blobs (100KB+).

Global configuration:

// Configure the pool size (defaults to number of processor cores)
// This is automatically initialized by QueryClient
IsolatePool.concurrency = 4; // Optional manual config

Offloading a task:

Future<List<User>> fetchAndParseUsers() async {
final response = await http.get(...);
// Use IsolatePool to parse JSON in a background thread
return IsolatePool().compute(
(jsonString) {
final List data = jsonDecode(jsonString);
return data.map((e) => User.fromJson(e)).toList();
},
response.body,
);
}

This ensures your UI animation stays at 60/120fps while parsing megabytes of data.

Fasq provides comprehensive performance monitoring to help you understand query behavior, cache efficiency, and system health.

The QueryClient exposes methods to retrieve detailed performance metrics:

final client = QueryClient();
// Get global performance snapshot
final snapshot = client.getMetrics();
print('Cache hit rate: ${(snapshot.cacheMetrics.hitRate * 100).toStringAsFixed(1)}%');
print('Total queries: ${snapshot.totalQueries}');
print('Active queries: ${snapshot.activeQueries}');
print('Memory usage: ${(snapshot.memoryUsageBytes / 1024 / 1024).toStringAsFixed(2)} MB');

Get detailed metrics for individual queries:

final metrics = client.getQueryMetrics('todos'.toQueryKey());
if (metrics != null) {
print('Fetch count: ${metrics.fetchCount}');
print('Average fetch time: ${metrics.averageFetchTime?.inMilliseconds}ms');
print('Max fetch time: ${metrics.maxFetchTime?.inMilliseconds}ms');
print('Reference count: ${metrics.referenceCount}');
// Throughput metrics (if available)
if (metrics.throughputMetrics != null) {
print('Requests per minute: ${metrics.throughputMetrics!.requestsPerMinute.toStringAsFixed(2)}');
print('Requests per second: ${metrics.throughputMetrics!.requestsPerSecond.toStringAsFixed(2)}');
}
}

A PerformanceSnapshot contains:

  • Cache Metrics: Hit rate, misses, evictions, fetch times
  • Query Metrics: Per-query performance data including fetch history and throughput
  • Memory Usage: Current and peak memory consumption
  • Query Statistics: Total and active query counts

Fasq automatically tracks query execution throughput (requests per minute/second) using rolling time windows:

// Get metrics with custom throughput window (default: 1 minute)
final snapshot = client.getMetrics(
throughputWindow: Duration(minutes: 5),
);
// Query-specific throughput
final metrics = client.getQueryMetrics(
'todos'.toQueryKey(),
throughputWindow: Duration(minutes: 5),
);

You can inspect the cache health to optimize your configurations:

final cacheInfo = client.getCacheInfo();
print('Cache entries: ${cacheInfo.entryCount}');
print('Cache size: ${(cacheInfo.sizeBytes / 1024 / 1024).toStringAsFixed(2)} MB');
print('Cache usage: ${(cacheInfo.usagePercentage * 100).toStringAsFixed(1)}%');
print('Hit rate: ${(cacheInfo.metrics.hitRate * 100).toStringAsFixed(1)}%');

Fasq exposes a HotCache class, which is a specialized high-performance LRU cache designed for extremely frequent access patterns (O(1) access).

While QueryCache manages async Query state, HotCache<T> is a synchronous memory cache for direct object storage.

final hotCache = HotCache<String>(maxSize: 100);
// Add items
hotCache.put('key1', 'value1');
// Retrieve (updates LRU position)
final value = hotCache.get('key1');

Use this if you need to build a custom synchronous memory layer on top of Fasq’s async primitives.