Profiling #
Sebelum mengoptimasi, kamu harus tahu apa yang lambat. Menebak bottleneck performa tanpa data adalah membuang waktu — seringkali kita mengoptimasi kode yang sudah cepat, sementara masalah sesungguhnya ada di tempat lain. Flutter DevTools memberikan visibilitas penuh ke setiap frame yang dirender, setiap fungsi yang memakan CPU, dan setiap objek di memori. Profiling adalah langkah pertama yang wajib dilakukan sebelum menulis satu baris optimasi.
Profile Mode — Prasyarat Profiling #
Jangan pernah profiling di debug mode. Debug mode mematikan optimasi compiler dan menambahkan overhead yang besar — angka yang kamu lihat tidak mencerminkan performa nyata.
# Jalankan di profile mode -- mirip release tapi bisa connect ke DevTools
flutter run --profile
# Build APK/IPA di profile mode untuk test di device fisik
flutter build apk --profile
flutter build ios --profile
# Buka DevTools dari terminal
flutter pub global activate devtools
flutter pub global run devtools
# Atau langsung dari VS Code / Android Studio via menu
# Flag tambahan yang berguna saat profiling
flutter run --profile --trace-skia # lihat operasi Skia/Impeller
flutter run --profile --enable-software-rendering # debug raster issue
Selalu profiling di device fisik, bukan emulator. Performa emulator jauh berbeda dari perangkat nyata. Gunakan perangkat dengan spesifikasi terendah yang mewakili pengguna kamu untuk mendapat gambaran terburuk yang mungkin terjadi.
Performance View — Frame Chart #
Performance view adalah titik masuk utama untuk menemukan jank (animasi yang tersendat):
Buka DevTools → tab "Performance"
Komponen utama:
┌─────────────────────────────────────────────────────────┐
│ Frame Chart │
│ ████ ████ ████ ████████ ████ ████ ████ ████ ████ │
│ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ ┊ │
│ UI Thread ↑ merah = frame > 16ms (jank di 60fps) │
│ Raster Thread │
└─────────────────────────────────────────────────────────┘
Cara baca:
Bar HIJAU -- frame selesai dalam budget (< 16ms untuk 60fps)
Bar MERAH -- frame terlambat, pengguna melihat jank
Bar BIRU -- frame di atas 16ms tapi masih di bawah 32ms
Target frame budget:
60fps → tiap frame ≤ 16ms
90fps → tiap frame ≤ 11ms
120fps → tiap frame ≤ 8ms
Alur Kerja Profiling Frame #
1. Tekan Record di DevTools
2. Lakukan interaksi yang terasa lambat (scroll, animasi, navigasi)
3. Tekan Stop
4. Klik frame merah di chart
5. Lihat tab "Frame Analysis" -- hints otomatis dari Flutter
6. Lihat tab "Timeline Events" -- detail setiap event dalam frame
7. Buka Flame Chart untuk melihat call stack CPU
CPU Profiler — Flame Chart #
Flame chart menunjukkan fungsi mana yang memakan waktu CPU paling banyak:
Cara membaca Flame Chart:
┌────────────────────────────┐
│ build (50ms total) │ ← terlihat lebar = mahal
│ ┌──────┐ ┌─────────────┐ │
│ │layout│ │ _buildList│ │
│ └──────┘ │ ┌──────────┐│ │
│ │ │ ListTile ││ │
│ │ └──────────┘│ │
│ └─────────────┘ │
└────────────────────────────┘
Sumbu X = waktu
Sumbu Y = kedalaman call stack (atas = caller, bawah = callee)
Lebar bar = waktu yang dihabiskan di dalam fungsi itu (termasuk callee-nya)
Kolom yang perlu diperhatikan:
Total Time -- waktu termasuk semua fungsi yang dipanggil di dalamnya
Self Time -- waktu fungsi itu sendiri, tanpa callee
↑ Self Time tinggi = BOTTLENECK -- fungsi ini sendiri yang lambat
// Tambahkan marker kustom agar mudah diidentifikasi di Flame Chart
import 'dart:developer' as developer;
void loadProduk() {
developer.Timeline.startSync('LoadProduk'); // mulai marker
try {
final data = repository.fetchProduk();
processData(data);
} finally {
developer.Timeline.finishSync(); // akhiri marker
}
}
// Atau gunakan UserTag untuk group profiling
final tag = developer.UserTag('MyExpensiveOperation');
final previousTag = tag.makeCurrent();
// ... operasi mahal di sini
previousTag.makeCurrent();
Memory Profiler — Heap Snapshot #
Memory profiler membantu menemukan memory leak dan alokasi berlebihan:
Buka DevTools → tab "Memory"
Tampilan utama:
Memory Chart -- grafik penggunaan memori real-time
─── Allocated (heap capacity)
─── Used (objek yang aktif di heap)
↓ GC event -- Garbage Collection terjadi
Indikator masalah:
✗ Grafik terus naik tanpa turun → memory leak
✗ Spike besar saat interaksi → alokasi berlebihan
✗ GC sangat sering → banyak objek sementara dibuat-dibuang
Mengambil Heap Snapshot #
1. Navigasi ke fitur yang dicurigai leak
2. Tekan "Snapshot" di tab Memory
3. Navigasi kembali (seharusnya data ter-GC)
4. Tekan "Snapshot" lagi
5. Klik "Diff" antara dua snapshot
6. Lihat objek yang jumlahnya BERTAMBAH -- itu yang leak
Yang perlu dicari di snapshot:
- Element dan RenderObject yang masih ada setelah halaman di-pop
- Listener, controller, stream yang tidak di-dispose
- Image dan byte array besar yang tidak di-cache atau ter-GC
// Contoh memory leak umum -- listener tidak di-dispose
// ANTI-PATTERN: StreamController tidak ditutup
class ProdukNotifier extends ChangeNotifier {
StreamSubscription? _sub;
void init() {
_sub = dataStream.listen((data) {
notifyListeners();
});
// LUPA dispose! _sub tidak pernah ditutup
}
// Tidak ada @override void dispose()
}
// BENAR: selalu dispose resource
class ProdukNotifier extends ChangeNotifier {
StreamSubscription? _sub;
void init() {
_sub = dataStream.listen((data) {
notifyListeners();
});
}
@override
void dispose() {
_sub?.cancel(); // tutup stream subscription
super.dispose();
}
}
Widget Inspector — Rebuild Analysis #
Widget Inspector menampilkan widget tree dan bisa menghighlight widget yang rebuild terlalu sering:
Buka DevTools → tab "Flutter Inspector"
Fitur berguna:
"Highlight Repaints" -- warna berkedip saat widget repaint
"Show Guidelines" -- tampilkan layout boundaries
"Select Widget Mode" -- klik widget di app untuk inspect
Di Performance view:
"Track Widget Builds" -- aktifkan untuk lihat jumlah rebuild per widget
"Track Repaints" -- highlight area yang di-repaint
# Atau aktifkan performance overlay langsung di app
# Tekan 'P' saat app berjalan di terminal
# atau tambahkan secara programatik:
// Aktifkan performance overlay saat development
MaterialApp(
showPerformanceOverlay: kDebugMode, // hanya saat debug
checkerboardRasterCacheImages: kDebugMode, // debug cache gambar
home: const HomeScreen(),
)
Alur Kerja Menemukan Jank #
GEJALA: Scroll/animasi terasa tidak mulus
LANGKAH 1 -- Cek thread mana yang lambat
Buka Performance view → lihat frame merah
├── UI Thread lambat → masalah di Dart code (build/layout/paint)
│ └── Buka CPU profiler → cari fungsi dengan Self Time tinggi
└── Raster Thread lambat → masalah di GPU/rendering
└── Cek: shader compilation, terlalu banyak layer, gambar besar
LANGKAH 2 -- Identifikasi penyebab
UI Thread lambat:
├── Build terlalu sering → gunakan const, select provider, ListView.builder
├── Layout mahal → cek widget Opacity, ClipRect, BackdropFilter
└── Komputasi berat di main isolate → pindah ke Isolate
Raster Thread lambat:
├── Shader compilation jank → warmup shader atau Impeller
├── Image terlalu besar → resize sebelum load
└── Terlalu banyak layer → kurangi RepaintBoundary yang tidak perlu
LANGKAH 3 -- Fix dan verifikasi
Perbaiki satu masalah → profile ulang → bandingkan before/after
Jangan fix semua sekaligus -- tidak akan tahu mana yang berpengaruh
Ringkasan #
- Selalu profiling di profile mode (
flutter run --profile) di device fisik — debug mode tidak representatif karena optimasi compiler dimatikan.- Performance view menampilkan frame chart — bar merah adalah frame yang melebihi budget (>16ms untuk 60fps). Klik frame merah untuk detail.
- Flame Chart di CPU Profiler menunjukkan fungsi mana yang mahal — perhatikan Self Time untuk menemukan bottleneck sesungguhnya.
- Memory Profiler menampilkan grafik heap real-time. Grafik yang terus naik tanpa turun adalah tanda memory leak. Gunakan heap snapshot diff untuk mengidentifikasi objek yang bocor.
- Penyebab umum jank di UI thread: terlalu banyak rebuild, komputasi berat di main isolate. Penyebab umum di Raster thread: shader compilation, gambar yang tidak di-resize, terlalu banyak layer.
- Tambahkan custom timeline marker dengan
developer.Timeline.startSync()untuk lebih mudah mengidentifikasi kode kamu di Flame Chart.- Fix satu masalah per iterasi lalu profile ulang — jangan optimasi banyak sekaligus, kamu tidak akan tahu mana yang benar-benar membantu.
← Sebelumnya: Testing Best Practice Berikutnya: Rendering Optimization →