Skip to main content

flutter_perf_guard 1.0.0 copy "flutter_perf_guard: ^1.0.0" to clipboard
flutter_perf_guard: ^1.0.0 copied to clipboard

Enterprise-grade Flutter performance analysis, debugging, profiling, and optimization toolkit for production-scale applications. Includes frame analysis, jank detection, memory leak detection, rebui [...]

flutter_perf_guard #

pub.dev License: MIT Flutter Platforms

Enterprise-grade Flutter performance analysis, debugging, profiling, and optimization toolkit for production-scale applications.


Features #

Category Feature
Frame Analysis Per-frame build/raster timing, rolling FPS, worst-frame detection
Jank Detection Consecutive-jank detection, dropped-frame counting, jank events
Memory Profiling Heap sampling, leak detection via linear regression, GC tracking
Rebuild Tracking Widget rebuild frequency, file name + line (debug), ancestor path, hot-widget ranking
Network Profiling HTTP request timing, status, size, slow/failed detection via HttpOverrides
Async Profiling Named async operation tracking with slow/failed detection
Image Cache Analysis Cache hit rate, size pressure, plain English fix suggestions
Performance Grading A–F grade per category with plain English summaries
Real-time Dashboard Full-screen diagnostics dashboard with frames, memory, rebuilds, event log
Performance Overlay Lightweight HUD with FPS, build/raster times, memory, jank alerts
Timeline Recording Bounded circular-buffer timeline with JSON export
Benchmark Engine Statistical micro-benchmark runner (mean, median, p95, p99, stddev)
Startup Analysis App-start to interactive milestone tracking
Navigation Tracking Route transition duration monitoring
Report Export Human-readable .txt report + JSON snapshot with grades and file locations
Event Bus Centralized typed DiagnosticsEventBus with RxDart streams

Installation #

dependencies:
  flutter_perf_guard: ^1.0.0

Quick Start #

1. Initialize #

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await PerfGuard.initialize(
    config: const PerfGuardConfig(
      enableFrameProfiler: true,
      enableMemoryProfiler: true,
      enableRebuildTracker: true,     // debug mode only
      enableJankDetector: true,
      enableNetworkProfiler: true,    // intercepts all HTTP requests
      enableAsyncProfiler: true,      // track named async operations
      verbose: true,
    ),
  );

  runApp(const MyApp());
}

2. Track async operations (optional) #

// Wrap any async call to measure it:
final products = await PerfGuard.instance.asyncProfiler.track(
  'fetch_products',
  () => api.getProducts(),
);

3. Export a readable report #

// Exports a human-readable .txt file to app documents directory
final path = await PerfGuard.instance.exportReport(
  format: ReportFormat.text,
);
print('Report saved to: $path');

4. Add the Overlay HUD #

Wrap your root widget (or any subtree) with PerfGuardOverlay:

MaterialApp(
  home: PerfGuardOverlay(
    showFps: true,
    showMemory: true,
    showJankAlert: true,
    child: MyHomePage(),
  ),
)

5. Open the Dashboard #

Navigator.of(context).push(
  MaterialPageRoute(builder: (_) => const DiagnosticsDashboard()),
);

6. Subscribe to Events #

final bus = DiagnosticsEventBus.instance;

// All frame events
bus.frameEvents.listen((e) {
  print('Frame #${e.metrics.frameNumber}: ${e.metrics.fps.toStringAsFixed(1)} FPS');
});

// Jank alerts only
bus.jankEvents.listen((e) {
  print('JANK: ${e.droppedFrames} dropped frames');
});

// All critical events
bus.criticalEvents.listen((e) {
  print('CRITICAL: ${e.source} – ${e.severity.label}');
});

Configuration #

const PerfGuardConfig(
  // Module toggles
  enableFrameProfiler: true,
  enableMemoryProfiler: true,
  enableRebuildTracker: true,   // debug mode only
  enableJankDetector: true,
  enableDashboard: true,
  enableStartupAnalyzer: true,
  enableNavigationTracker: true,
  enableAsyncProfiler: false,
  enableNetworkProfiler: false,

  // Thresholds
  jankThreshold: Duration(milliseconds: 16),
  slowFrameThreshold: Duration(milliseconds: 8),
  consecutiveJankFramesThreshold: 3,
  memoryWarningThreshold: 0.80,   // 80% heap
  memoryCriticalThreshold: 0.92,

  // Sampling
  memorySamplingInterval: Duration(seconds: 2),
  frameHistorySize: 300,

  // Export
  autoExportOnCritical: false,
  exportDirectory: '/tmp/perf_guard_reports',

  verbose: false,
)

Presets available:

PerfGuardConfig.minimal  // Frame + jank only, lowest overhead
PerfGuardConfig.full     // All modules enabled

API Reference #

PerfGuard (Singleton) #

// Initialize
await PerfGuard.initialize(config: myConfig);

// Access sub-components
PerfGuard.instance.frameProfiler
PerfGuard.instance.memoryProfiler
PerfGuard.instance.rebuildTracker
PerfGuard.instance.timelineRecorder
PerfGuard.instance.startupAnalyzer
PerfGuard.instance.navigationTracker

// Export
final path = await PerfGuard.instance.exportReport();
final map = await PerfGuard.instance.takeSnapshot();

// Pause/resume (e.g. on background)
PerfGuard.instance.pause();
PerfGuard.instance.resume();

FrameProfiler #

final fp = PerfGuard.instance.frameProfiler;

fp.currentFps()          // rolling 60-frame average
fp.averageFrameTime      // Duration
fp.jankRate              // 0.0–1.0
fp.jankFrames            // int
fp.totalFrames           // int
fp.history               // List<FrameMetrics>
fp.worstFrameDuration    // Duration

MemoryProfiler #

final mp = PerfGuard.instance.memoryProfiler;

mp.latest          // MemoryMetrics?
mp.history         // List<MemoryMetrics>
mp.averageHeapMb   // double
mp.peakHeapBytes   // int

RebuildTracker #

final rt = PerfGuard.instance.rebuildTracker;

rt.allMetrics          // List<RebuildMetrics>
rt.hotWidgets          // Top 20 by rebuild count
rt.excessiveRebuilds   // Widgets rebuilding > 60/s
rt.reset()

TimelineRecorder #

final rec = PerfGuard.instance.timelineRecorder;

rec.start(maxEntries: 5000);
// ... your app runs ...
rec.stop();

final json = rec.exportJson(pretty: true);

BenchmarkRunner #

final suite = BenchmarkSuite(name: 'MyBenchmarks')
  ..add('list_sort', () {
    final l = List.generate(1000, (i) => i);
    l.sort();
  })
  ..addAsync('db_query', () async {
    await Future.delayed(const Duration(milliseconds: 5));
  });

const runner = BenchmarkRunner(defaultMeasuredRuns: 20);
final results = await runner.run(suite);

for (final r in results) {
  print('${r.name}: mean=${r.mean.inMilliseconds}ms p95=${r.p95.inMilliseconds}ms');
}

NetworkProfiler #

final np = PerfGuard.instance.networkProfiler;

np.records           // List<NetworkRequestRecord> — all requests
np.slowRequests      // requests taking > 1 second
np.failedRequests    // requests with status >= 400 or errors
np.plainEnglishSummary  // human-readable summary string

AsyncProfiler #

final ap = PerfGuard.instance.asyncProfiler;

// Track any async operation by name:
final result = await ap.track('load_user', () => fetchUser(id));

// Track synchronous expensive work:
final sorted = ap.trackSync('sort_products', () => products.sort(...));

ap.slowOperations      // List<AsyncOperationRecord>
ap.failedOperations    // List<AsyncOperationRecord>
ap.plainEnglishSummary // human-readable summary
ap.reset()

ImageCacheAnalyzer #

final ia = PerfGuard.instance.imageCacheAnalyzer;

final snap = ia.snapshot();
snap.currentCount      // int — cached image count
snap.currentSizeMb     // double — cache size in MB
snap.usagePercent      // double — 0.0–1.0
ia.plainEnglishSummary // human-readable summary
ia.trimCacheTo(50 * 1024 * 1024); // trim to 50MB
ia.clearCache();

PerformanceGrader #

final grader = PerformanceGrader(
  frameProfiler: PerfGuard.instance.frameProfiler,
  memoryProfiler: PerfGuard.instance.memoryProfiler,
  rebuildTracker: PerfGuard.instance.rebuildTracker,
  navigationTracker: PerfGuard.instance.navigationTracker,
);

grader.gradeFrames()    // PerformanceGrade.A / B / C / D / F
grader.gradeMemory()
grader.gradeRebuilds()
grader.overallGrade     // worst category grade
grader.frameSummary()   // "✅ Excellent — 59.8 FPS, no jank detected"
grader.rebuildSummary() // "❌ ProductCard rebuilding 94x/sec\n   File: lib/screens/home_screen.dart:142"

Add the observer to your MaterialApp:

MaterialApp(
  navigatorObservers: [
    PerfGuard.instance.navigationTracker,
  ],
  ...
)

Architecture #

flutter_perf_guard/
├── lib/
│   ├── flutter_perf_guard.dart          # Public exports
│   └── src/
│       ├── public_api/                  # Public API Layer
│       │   ├── perf_guard.dart          # Singleton entry point
│       │   ├── perf_guard_config.dart
│       │   ├── performance_monitor.dart
│       │   ├── frame_profiler.dart
│       │   ├── memory_profiler.dart
│       │   ├── rebuild_tracker.dart
│       │   ├── timeline_recorder.dart
│       │   ├── benchmark_runner.dart
│       │   ├── performance_overlay_widget.dart
│       │   └── diagnostics_dashboard.dart
│       ├── core/                        # Core Infrastructure
│       │   ├── bus/diagnostics_event_bus.dart
│       │   └── events/                  # Typed events
│       ├── profiling/                   # Data Models
│       │   ├── frame/frame_metrics.dart
│       │   ├── memory/memory_metrics.dart
│       │   └── rebuild/
│       │       ├── rebuild_metrics.dart
│       │       └── rebuild_location.dart
│       ├── monitoring/                  # Specialized Monitors
│       │   ├── startup/startup_analyzer.dart
│       │   └── navigation/navigation_tracker.dart
│       │   ├── network/network_profiler.dart 
│       │   ├── async/async_profiler.dart      
│       │   └── image/image_cache_analyzer.dart 
│       ├── analysis/                    # Analysis Reports
│       │   ├── grader/performance_grader.dart
│       │   ├── jank/jank_report.dart
│       │   ├── repaint/repaint_report.dart
│       │   └── layout/layout_report.dart
│       ├── export/                      # Report Generation
│       │   ├── profiling_report.dart
│       │   └── report_exporter.dart
│       │   ├── file_writer.dart               
│       │   ├── file_writer_web.dart           
│       │   └── formatters/
│       │       └── text_formatter.dart        
│       └── benchmark/                   # Benchmark Engine
│           ├── benchmark_suite.dart
│           └── benchmark_result.dart
├── test/
│   ├── unit/
│   ├── rendering/
│   ├── stress/
│   └── benchmark/
└── example/

Performance Overhead #

flutter_perf_guard is designed for zero-cost in release builds:

  • RebuildTracker is only active in debug mode (uses debugOnRebuildDirtyWidget)
  • FrameProfiler uses Flutter's native SchedulerBinding.addTimingsCallback
  • MemoryProfiler samples on a timer (default 2s interval) – not per-frame
  • PerfGuardOverlay uses IgnorePointer and only rebuilds on event receipt
  • All streams are lazy (no work until someone subscribes)

Typical overhead in profile mode: < 1% CPU, < 2MB RAM.


Export Formats #

Human-Readable Text (default) #

final path = await PerfGuard.instance.exportReport(
  format: ReportFormat.text,
);
Output example:
════════════════════════════════════════════════════════════
flutter_perf_guard 
Performance Report
2024-06-10 10:30:00
════════════════════════════════════════════════════════════
OVERALL GRADE : 🟡 C
FRAMES   🟢 A
────────────────────────────────────────────────────────────
Average FPS      : 59.8
Jank Events      : 0
Worst Frame      : 9ms  (budget: 16ms)
Summary          : ✅ Excellent — 59.8 FPS, no jank detected
MEMORY   🟢 A
────────────────────────────────────────────────────────────
Heap Used        : 42.1MB
Heap Capacity    : 180.0MB
Heap Usage       : 23%
Summary          : ✅ Healthy — 42.1MB heap (23% used)
REBUILDS   🔴 F
────────────────────────────────────────────────────────────
Top Offenders:

ProductCard             94/sec ← EXCESSIVE
File: lib/screens/home_screen.dart:142
Path: HomeScreen > Column > ListView > ProductCard
CounterWidget           58/sec ← EXCESSIVE
File: lib/widgets/counter.dart:38

WHAT TO FIX
════════════════════════════════════════════════════════════

REBUILD — ProductCard rebuilding 94x/sec
File: lib/screens/home_screen.dart:142 //If available
Location: HomeScreen > Column > ListView > ProductCard
→ Add const or use ValueListenableBuilder
REBUILD — CounterWidget rebuilding 58x/sec
File: lib/widgets/counter.dart:38
→ Add const or use ValueListenableBuilder
════════════════════════════════════════════════════════════

JSON (structured data) #

final path = await PerfGuard.instance.exportReport(
  format: ReportFormat.json,
);
{
  "grade": {
    "overall": "C",
    "frames":   { "grade": "A", "summary": "✅ Excellent — 59.8 FPS" },
    "memory":   { "grade": "A", "summary": "✅ Healthy — 42.1MB" },
    "rebuilds": { "grade": "F", "summary": "❌ 2 widget(s) rebuilding excessively" }
  },
  "rebuild": {
    "hotWidgets": [
      {
        "widgetType": "ProductCard",
        "rebuildsPerSecond": 94.0,
        "location": {
          "fileInfo": "lib/screens/home_screen.dart:142",
          "ancestorPath": "HomeScreen > Column > ListView > ProductCard"
        }
      }
    ]
  },
  "optimizationSuggestions": [
    {
      "category": "rebuild",
      "widget": "ProductCard",
      "rebuildsPerSec": "94",
      "file": "lib/screens/home_screen.dart:142",
      "location": "HomeScreen > Column > ListView > ProductCard",
      "message": "ProductCard rebuilding 94x/sec — add const or use RepaintBoundary"
    }
  ]
}

License #

MIT © 2024 flutter_perf_guard contributors. See LICENSE.

14
likes
130
points
28
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Enterprise-grade Flutter performance analysis, debugging, profiling, and optimization toolkit for production-scale applications. Includes frame analysis, jank detection, memory leak detection, rebuild tracking, Image cache analyzing, Network request profiling, real-time dashboards, and exportable profiling reports.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

async, equatable, flutter, intl, json_annotation, logging, path, path_provider, rxdart, synchronized, web

More

Packages that depend on flutter_perf_guard