Performance Profiling
Debugging bukan hanya tentang error — aplikasi yang lambat juga perlu di-debug. Performance profiling membantu menemukan bottleneck di aplikasi.
Performance Panel di DevTools
- Buka DevTools → tab Performance
- Klik Record (atau
Ctrl+E) - Lakukan aksi yang ingin diukur
- Klik Stop
- Analisis hasilnya
Membaca Flame Chart
Flame chart menampilkan apa yang browser lakukan selama recording:
Waktu →
├── Task (50ms)
│ ├── Parse HTML (5ms)
│ ├── Evaluate Script (30ms)
│ │ ├── fetchData() (20ms)
│ │ └── renderList() (10ms)
│ └── Layout (10ms)
│ └── Style recalculation (5ms)
└── Paint (3ms)
- Semakin lebar sebuah bar = semakin lama eksekusinya
- Warna menunjukkan kategori: kuning (Script), ungu (Layout), hijau (Paint)
- Cari task yang lebih dari 50ms (menyebabkan jank)
Flame Chart Anatomy
Cara baca cepat:
- Vertikal = call stack. Function di atas dipanggil oleh function di bawahnya.
- Horizontal = urutan waktu eksekusi, lebar = durasi.
- Plateau lebar di atas = function yang banyak menghabiskan waktu sendiri (bukan delegate ke child) → kandidat optimasi pertama.
- Tinggi stack yang panjang = rekursi dalam atau framework overhead — wajar di React/Vue, tidak selalu masalah.
Di Chrome Performance panel, beralih ke Bottom-Up view untuk list function sorted by self time descending — langsung fokus ke hotspot tanpa harus scan flame chart manual.
Mengukur dengan JavaScript
performance.now()
const start = performance.now();
// ... operasi yang ingin diukur ...
const data = processLargeArray(items);
const end = performance.now();
console.log(`Waktu: ${(end - start).toFixed(2)}ms`);
Performance API
// Mark titik waktu tertentu
performance.mark("fetch-start");
await fetch("/api/data");
performance.mark("fetch-end");
// Ukur jarak antara dua mark
performance.measure("fetch-duration", "fetch-start", "fetch-end");
const measures = performance.getEntriesByName("fetch-duration");
console.log(`Fetch: ${measures[0].duration.toFixed(2)}ms`);
Masalah Performance Umum
1. Layout Thrashing
// ❌ Membaca dan menulis DOM bergantian (layout thrashing)
for (const el of elements) {
const height = el.offsetHeight; // READ → trigger layout
el.style.height = height * 2 + "px"; // WRITE → invalidate layout
// Loop berikutnya: READ lagi → layout lagi!
}
// ✅ Batch reads, then batch writes
const heights = elements.map(el => el.offsetHeight); // Batch READ
elements.forEach((el, i) => {
el.style.height = heights[i] * 2 + "px"; // Batch WRITE
});
2. Memory Leak
// ❌ Event listener tidak di-cleanup
useEffect(() => {
window.addEventListener("resize", handleResize);
// Lupa cleanup → listener terus menumpuk!
}, []);
// ✅ Cleanup saat unmount
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
3. Rendering Berlebihan
// ❌ Render ulang seluruh list saat satu item berubah
function TodoList({ items }) {
return items.map(item => <TodoItem key={item.id} {...item} />);
}
// ✅ Memo untuk mencegah re-render yang tidak perlu
const TodoItem = React.memo(function TodoItem({ id, text, done }) {
return <div>{text}</div>;
});
Lighthouse
Lighthouse adalah tool audit bawaan Chrome yang mengukur performa secara keseluruhan:
- DevTools → tab Lighthouse
- Pilih kategori (Performance, Accessibility, dll)
- Klik Analyze page load
Metrics utama:
- FCP (First Contentful Paint) — kapan konten pertama muncul
- LCP (Largest Contentful Paint) — kapan elemen terbesar muncul
- TBT (Total Blocking Time) — total waktu thread utama diblokir
- CLS (Cumulative Layout Shift) — seberapa banyak layout bergeser
Memory Panel
Untuk debugging memory leak:
- DevTools → Memory tab
- Heap snapshot — foto alokasi memory saat ini
- Allocation timeline — track alokasi seiring waktu
Cari object yang terus bertambah tapi tidak di-garbage collect.
console.time untuk Profiling Cepat
console.time("render");
renderComponent();
console.timeEnd("render"); // render: 23.456ms
// Atau gunakan console.profile (lebih detail)
console.profile("my-function");
myHeavyFunction();
console.profileEnd("my-function");
// Hasilnya muncul di Performance panel
Tips
- Jangan optimize prematur — ukur dulu, optimize yang benar-benar bermasalah
- Gunakan production build saat profiling — development mode lebih lambat
- Test di device nyata — laptop developer tidak merepresentasikan user
- Target 60fps — setiap frame harus selesai dalam ~16ms
- Lighthouse score bukan segalanya — user experience yang penting