Performance profiling adalah merekam apa saja yang dikerjakan browser, milidetik demi milidetik, supaya kamu tahu persis apa yang bikin halaman lambat. Bayangin manajer proyek. Total waktu proyeknya 60 hari, tapi pekerjaan yang dia kerjakan sendiri cuma 5 hari; sisanya dikerjakan timnya. Kalau mau proyeknya lebih cepat, gak ada gunanya menekan si manajer: cari anggota tim yang kerjanya paling lama. Flame chart di DevTools menunjukkan dua angka itu untuk tiap fungsi: total waktunya, dan waktu miliknya sendiri.
🧪 Tebakan cepat: di flame chart,
taskmakan 60 ms. Di dalamnya adaparseHTML10 ms danscript45 ms. Berapa ms yang benar-benar dikerjakantasksendiri? Tebak dulu, jawabannya ada di bagian "Total time dan self time".
Merekam di panel Performance
- Buka DevTools, pilih panel Performance. Halaman awalnya sudah menampilkan LCP, CLS, dan INP dari interaksimu secara live.
- Klik Record (Ctrl+E; di Mac Cmd+E), lakukan aksi yang terasa lambat (klik, scroll, ketik), lalu klik Stop. Untuk mengukur halaman dimuat, pakai Record and reload (Ctrl+Shift+E).
- DevTools menampilkan rekamannya. Track Main adalah thread utama, tempat JavaScript, layout, dan paint berjalan bergantian.
Laptop developer jauh lebih kencang dari HP kebanyakan user. Sebelum merekam, setel CPU throttling ke 4x slowdown, dan rekam di jendela incognito supaya extension gak ikut tercatat.
Membaca flame chart
Lab di pelajaran ini merekam kode sungguhan: satu task yang memanggil fungsi-fungsi yang sengaja sibuk selama waktu tertentu, lalu task kedua bernama paint, dan mencatat waktu mulai dan selesai tiap fungsi dengan performance.now(). Hasilnya enam sampel seperti di latihan (rekaman asli bisa meleset sepersekian milidetik):
| Sampel | Mulai | Selesai | Induk |
|---|---|---|---|
task |
0 ms | 60 ms | (paling atas) |
parseHTML |
0 ms | 10 ms | task |
script |
10 ms | 55 ms | task |
fetch |
10 ms | 30 ms | script |
render |
30 ms | 55 ms | script |
paint |
60 ms | 70 ms | (paling atas) |
Digambar sebagai flame chart:
0 10 30 55 60 70 ms
[task.............................................]
[parseHTML][script...............................]
[fetch..........][render...........]
[paint...]
- Ke kanan adalah waktu. Makin lebar sebuah bar, makin lama ia berjalan.
- Ke bawah adalah pemanggilan. Bar di bawah dipanggil oleh bar di atasnya:
fetchdanrenderdipanggilscript. - Warna di Chrome menunjukkan jenis kerjanya: kuning untuk JavaScript (Scripting), ungu untuk Recalculate Style dan Layout (Rendering), hijau untuk Paint, abu-abu untuk Task dan kerja sistem.
- Klik satu bar, dan tab Summary di bawah menunjukkan durasinya.
Total time dan self time
- Total time: lebar bar, dari mulai sampai selesai, termasuk semua fungsi yang dipanggilnya.
- Self time: total time dikurangi total time semua anak langsungnya. Waktu yang dikerjakan fungsi itu sendiri.
| Sampel | Total time | Anak langsung | Self time |
|---|---|---|---|
task |
60 ms | parseHTML 10 + script 45 |
60 - 55 = 5 ms |
parseHTML |
10 ms | 10 ms | |
script |
45 ms | fetch 20 + render 25 |
0 ms |
fetch |
20 ms | 20 ms | |
render |
25 ms | 25 ms |
task cuma mengerjakan 5 ms sendiri. Itu jawaban tebakannya. Fungsi dengan total besar tapi self kecil (task, script) cuma membagi kerja. Yang perlu dioptimasi adalah fungsi dengan self time terbesar, di sini render. Di DevTools, tab Bottom-up mengurutkan fungsi berdasarkan self time, jadi kandidat optimasinya langsung di baris paling atas. Tab Call tree mengurutkan dari atas pohon berdasarkan total time.
Long task dan jank
Supaya animasi dan scroll mulus di 60 fps, browser butuh satu frame tiap 16,7 ms (1.000 dibagi 60). Selama satu task JavaScript berjalan, thread utama sibuk: klik dan ketikan harus menunggu, dan frame baru gak bisa digambar.
Long task adalah task yang memblokir thread utama lebih dari 50 ms. Di Performance panel ia ditandai segitiga merah di pojok kanan atas, dan bagian yang lewat 50 ms diberi garis-garis merah. task di rekaman tadi 60 ms, jadi ia long task, dan paint (10 ms) bukan. Total Blocking Time (TBT) menjumlahkan bagian yang lewat 50 ms itu: task 60 ms menyumbang 10 ms.
Cara memperbaikinya:
- Kurangi kerjanya. Cari self time terbesar di Bottom-up, lalu buat fungsi itu lebih ringan.
- Pecah jadi beberapa task. Pindahkan sebagian kerja ke task berikutnya dengan
setTimeout(..., 0)(atauscheduler.yield()di Chrome), supaya browser sempat merespons di antaranya. Di Lab, memindahkanrenderke task sendiri menghasilkantask35 ms danrender25 ms: dua-duanya di bawah 50 ms. - Pindahkan hitungan berat ke Web Worker, yang berjalan di luar thread utama.
FPS dari cap waktu frame
FPS (frames per second) dihitung dari jarak antar frame: 1000 / rata-rata jarak.
| Cap waktu frame (ms) | Rata-rata jarak | FPS |
|---|---|---|
[0, 16, 32, 48, 64] |
64 / 4 = 16 ms | 1000 / 16 = 62,5, dibulatkan 63 |
[0, 100, 200] |
200 / 2 = 100 ms | 10 |
[0, 20, 40, 60] |
60 / 3 = 20 ms | 50 |
[0] |
gak ada jarak | 0 |
Rata-ratanya cukup dihitung dari cap terakhir dikurangi cap pertama, dibagi banyaknya jarak (banyak frame dikurangi 1). Dengan kurang dari dua frame belum ada jarak sama sekali, jadi hasilnya 0.
Mengukur langsung dari kode
console.time("render");
renderList(produk);
console.timeEnd("render"); // render: 23.4560546875 ms
const mulai = performance.now();
renderList(produk);
console.log(`${(performance.now() - mulai).toFixed(1)} ms`);
console.timedanconsole.timeEnddengan label yang sama mencetaklabel: waktu msdi Console.performance.now()memberi waktu dalam milidetik dengan pecahan, cocok untuk membandingkan dua versi fungsi.performance.mark("a")danperformance.measure("nama", "a", "b")membuat penanda yang muncul di track Timings saat kamu merekam di Performance panel.
🎯 Lighthouse atau Performance?
Lighthouse (panel Lighthouse, tombol Analyze page load) mengaudit satu kali pemuatan halaman dan memberi skor beserta saran, dari metrik FCP, LCP, TBT, CLS, dan Speed Index. Performance panel merekam apa saja yang kamu lakukan, termasuk klik dan scroll setelah halaman dimuat, sampai ke tiap fungsi. Lighthouse memberi tahu bahwa halaman lambat; Performance memberi tahu di mana. Rekam versi production, karena build development jauh lebih lambat dan menyesatkan angkanya.
⚠️ Jebakan yang sering ketemu
- Mengoptimasi fungsi dengan total time terbesar. Fungsi itu mungkin cuma memanggil yang lain. Lihat self time.
- Menebak tanpa merekam. "Kayaknya fetch-nya lambat" sering salah. Rekam dulu, baru ubah kode.
- Merekam di laptop kencang tanpa throttling. Task 30 ms di laptop bisa jadi 120 ms di HP.
- Di latihan: lupa pembulatan atau batas
0.selfdantotalpakaiMath.round, long task pakai>(bukan>=) dan diurutkan dari yang terlama, danfpsFromFramesdengan kurang dari dua cap waktu mengembalikan0.
TL;DR: Rekam aksi yang lambat di panel Performance (Ctrl+E), sebaiknya dengan CPU throttling. Di flame chart, ke kanan adalah waktu dan ke bawah adalah pemanggilan. Total time adalah lebar bar; self time adalah total dikurangi total anak langsungnya, dan yang dioptimasi adalah self time terbesar (tab Bottom-up). Task di atas 50 ms adalah long task yang bikin halaman tersendat; perbaiki dengan mengurangi kerja, memecahnya jadi beberapa task, atau memindahkannya ke Web Worker. Di contoh: task total 60 ms, self 5 ms, dan ia satu-satunya long task. FPS = 1000 dibagi rata-rata jarak antar frame: jarak 16 ms memberi 63 fps, jarak 100 ms memberi 10 fps, dan kurang dari dua frame memberi 0.