PERFORMANCE_OPTIMIZATIONS.md 4.3 KB

ZenTap Performance Optimizations

Problem Identified

The application was experiencing frame drops with the error "Skipped 31 frames! The application may be doing too much work on its main thread."

Root Causes and Solutions

1. Excessive Particle Effects on Bubble Pop

Problem: Each bubble pop created 8 particles with complex animations (scale, move, fade, gravity) lasting 500ms.

Solution:

  • Reduced particles from 8 to 4
  • Simplified effects by combining movement and gravity into single effect
  • Reduced animation duration from 500ms to 300ms
  • Removed scale effects to reduce computational load
  • File: lib/game/components/bubble.dart

2. High-Frequency Tilt Detection Updates

Problem: Accelerometer data was being processed at 10Hz (every 100ms) and immediately applied to all active bubbles.

Solutions:

  • Reduced accelerometer sampling rate from 10Hz to 5Hz (200ms intervals)
  • Added throttling to tilt force application (max 10 updates per second)
  • Implemented batched processing of bubble tilt forces to prevent frame blocking
  • Added async processing with Future.delayed(Duration.zero) between batches
  • Files:

3. Blocking Audio Operations

Problem: Audio playback was synchronous and could block the main thread.

Solution:

  • Made audio playback completely asynchronous
  • Split audio operations into separate async methods
  • Removed await calls from main playback method to prevent blocking
  • File: lib/game/audio/audio_manager.dart

4. Frequent Bubble Cleanup Operations

Problem: Bubble cleanup was running every frame in the update loop.

Solution:

Performance Improvements Summary

Optimization Before After Impact
Particle Count 8 per pop 4 per pop 50% reduction
Particle Duration 500ms 300ms 40% faster cleanup
Tilt Sampling Rate 10Hz 5Hz 50% fewer sensor events
Tilt Force Application Immediate Throttled to 10Hz + batched Prevents frame blocking
Audio Operations Synchronous Asynchronous No main thread blocking
Bubble Cleanup Every frame (~60Hz) Every 0.5s (2Hz) 97% reduction in cleanup frequency

Expected Results

These optimizations should significantly reduce main thread blocking and eliminate the frame skipping issues. The game should now maintain a smooth 60 FPS even with multiple bubbles and simultaneous interactions.

Technical Details

Async Processing Pattern

// Before: Blocking
await heavyOperation();

// After: Non-blocking
_heavyOperationAsync();

void _heavyOperationAsync() async {
  // Heavy work here
}

Batched Processing Pattern

// Process items in small batches with yielding
const batchSize = 3;
for (int i = 0; i < items.length; i += batchSize) {
  final batch = items.sublist(i, endIndex);
  // Process batch
  if (endIndex < items.length) {
    await Future.delayed(Duration.zero); // Yield control
  }
}

Throttling Pattern

double _lastUpdateTime = 0.0;
static const double updateInterval = 0.1;

void onEvent() {
  final currentTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
  if (currentTime - _lastUpdateTime >= updateInterval) {
    _lastUpdateTime = currentTime;
    // Process event
  }
}

Flutter Flame Integration

The implementation successfully uses Flutter Flame game engine with:

  • Flame Components: Custom bubble and spawner components
  • Flame Effects: Optimized scale, opacity, and movement effects
  • Flame Audio: Audio pools for efficient sound playback
  • Flame Collision Detection: Circle hitboxes for bubble interactions
  • Async Support: Proper async/await patterns that don't block the main thread

Monitoring

To monitor performance improvements:

  1. Check Flutter Inspector for frame rendering times
  2. Monitor console for frame skip warnings
  3. Use performance overlay: flutter run --profile
  4. Watch CPU usage during bubble interactions and tilt movements