Dua developer bisa berdebat lama soal versi kode mana yang lebih cepat — dan keduanya sama-sama menebak. Perasaan “tampaknya lebih cepat” bukan data. Profiling mengubah perdebatan itu menjadi angka: kita mencatat waktu sebelum, mengubah sesuatu, mencatat waktu sesudah, lalu membandingkan.

Kabar baiknya, stopwatch untuk pekerjaan ini sudah tersedia tanpa instalasi apa pun — baik di Node maupun di browser. Chapter ini melatih dua alat paling dasar: performance.now() untuk pengukuran manual, console.time/timeEnd untuk pencatatan berlabel, plus cara membaca hasilnya dengan jujur dan gambaran singkat profiler di DevTools.

performance.now(): Stopwatch dari Runtime #

Di Node, performance tersedia sebagai global — tanpa import apa pun (di browser pun sama). Method performance.now() mengembalikan satu angka bertipe number: waktu tingkat tinggi dalam milidetik, termasuk pecahan desimal. Karena nilainya cuma angka, pasangan mulai–selesai kita atur sendiri; selisihnya adalah durasi.

// ukur-profil.js — dua alat pengukuran waktu yang tersedia di Node

// 1. performance.now(): angka waktu mentah, kita atur sendiri pasangannya
const mulai = performance.now();
let total = 0;
for (let i = 1; i <= 100000; i++) {
  total += i;
}
const selesai = performance.now();
console.log("tipe data :", typeof mulai);
console.log("naik      :", selesai >= mulai);
console.log("durasi    :", (selesai - mulai).toFixed(3), "ms");
console.log("hasil     :", total);

// 2. console.time / timeEnd: pasangan label yang dicatat runtime
console.time("jumlah-100rb");
let total2 = 0;
for (let i = 1; i <= 100000; i++) {
  total2 += i;
}
console.timeEnd("jumlah-100rb");
console.log("hasil     :", total2);

Output yang Dihasilkan (angka waktu bervariasi antar mesin dan antar kali jalankan):

text
tipe data : number
naik      : true
durasi    : 1.122 ms
hasil     : 5000050000
jumlah-100rb: 1.926ms
hasil     : 5000050000

Mari kita telaah baris-baris pentingnya:

  1. Baris 4 dan 9 (performance.now()): dua pembacaan mengapit pekerjaan yang ingin diukur. Selisihnya adalah durasi loop — pekerjaan pembacaan sendiri sepele dibandingkan pekerjaan yang diapit.
  2. Baris 10–11 (typeof dan >=): dua baris ini menjawab pertanyaan yang bisa dijawab secara deterministik. tipe data : number dan naik : true berlaku di setiap mesin: performance.now() memang angka, dan waktunya selalu berjalan maju. Sebaliknya, baris durasi memang sengaja tidak deterministik — pembahasan lengkapnya di bagian akhir chapter.
  3. Baris 12 ((selesai - mulai).toFixed(3)): selisih dua angka now() adalah durasi dalam milidetik; toFixed(3) merapikannya menjadi tiga desimal agar mudah dibaca, misalnya 1.122.
  4. Baris 13 dan 22 (hasil : 5000050000): jumlah 1 sampai 100.000 tercetak sama persis di setiap run. Prinsip yang kita pegang sepanjang section ini: hasil hitungan bersifat pasti dan layak dibuktikan; waktu bersifat bervariasi dan hanya layak dibandingkan.
  5. Baris 16 dan 21 (console.time("jumlah-100rb") / timeEnd): pasangan berlabel. time memulai pencatatan untuk label tertentu; timeEnd menghentikannya dan langsung mencetak label: durasi ms — lihat baris jumlah-100rb: 1.926ms pada keluaran. Formatnya tetap, nilainya bervariasi.

Pasangan console.time/timeEnd paling nyaman untuk ukuran cepat tanpa variabel tambahan, sementara performance.now() lebih fleksibel — hasilnya bisa diakumulasi, dihitung rata-ratanya, atau dikirim ke log lain. Ada satu anggota keluarga lagi yang berguna saat pekerjaan berjalan lama: console.timeLog("jumlah-100rb") mencetak waktu berjalan sejauh ini untuk label yang aktif, tanpa menghentikan pencatatannya — berguna untuk menandai tengah-tengah proses sebelum timeEnd menutupnya.

Membaca Angka Pengukuran dengan Jujur #

Angka waktu punya sifat yang harus diakui sejak awal: durasi berbeda antar mesin, antar browser, dan antar kali jalankan. Loop yang sama mencetak 1.122 ms di satu run dan 1.048 ms di run berikutnya — keduanya benar. Cara membacanya:

  • Bandingkan rasio, bukan angka tunggal. Kesimpulan yang sah terletak pada selisih yang konsisten antara dua versi kode — misalnya versi B selalu sekitar sepuluh kali lebih cepat dari versi A — bukan pada satu angka indah.
  • Jalankan beberapa kali. Run pertama sering lebih lambat karena runtime masih menyiapkan segalanya; run berikutnya lebih mewakili kondisi pemakaian nyata. Protokol sederhana yang layak dijadikan kebiasaan: jalankan tiga kali, buang run pertama, catat dua sisanya.
  • Perbesar pekerjaan yang terlalu singkat. Mengukur pekerjaan yang selesai dalam mikrodetik seperti mengukur panjang pensil dengan penggaris rumah — selisihnya tenggelam di noise. Kalikan pekerjaannya (ulangi dalam loop seratus atau seribu kali) sampai durasinya cukup besar untuk dibaca.
  • Ingat biaya pengukuran itu sendiri. Kode pengukuran ikut makan waktu; untuk pekerjaan yang sangat singkat, ulangi pekerjaannya dalam loop dan ukur keseluruhan, seperti yang kita lakukan dengan 100.000 iterasi di atas.

Sekilas Profiler DevTools #

Pengukuran manual cocok untuk pertanyaan sempit: “loop ini berapa lama?”. Untuk pertanyaan luas — “di mana waktu aplikasi habis?” — alat yang tepat adalah profiler. Pada tab Performance di browser DevTools, kita merekam timeline selama aplikasi berjalan, lalu membaca grafik utamanya: tugas-tugas di main thread dan flame chart yang menumpuk pemanggilan function, sehingga function yang menyita waktu paling banyak langsung terlihat tinggi dan lebar di bagian atas tumpukan. Node punya jalur yang mirip: dijalankan dengan node --inspect, lalu diperiksa lewat DevTools Chrome.

Dua hal yang perlu dipegang saat membaca profiler: tugas panjang di main thread biasanya penyebab utama halaman tak responsif, dan hasil profiler selalu lebih besar dari kondisi normal karena pencatatan sendiri menambah beban. Gunakan profiler untuk menemukan titik panas; gunakan pengukuran manual untuk membuktikan perbaikannya.

Rutinitas membaca profiler bisa diringkas tiga langkah:

  1. Rekam timeline selama aksi yang dicurigai dilakukan (buka halaman, tekan tombol yang lambat).
  2. Cari blok terpanjang di main thread — blok itulah yang membuat interaksi tertahan.
  3. Perbesar blok itu pada flame chart dan baca nama function di puncak tumpukannya; nama tersebut adalah titik panas pertama yang layak diperiksa kodenya.

Stopwatch dan profiler sudah kita pegang untuk mengukur kode apa pun. Babak berikutnya turun ke lapisan yang lebih dekat dengan layar: berapa biaya setiap perubahan DOM yang kita buat.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

ukur-profil.js

Unduh berkas
javascript
// ukur-profil.js — dua alat pengukuran waktu yang tersedia di Node

// 1. performance.now(): angka waktu mentah, kita atur sendiri pasangannya
const mulai = performance.now();
let total = 0;
for (let i = 1; i <= 100000; i++) {
  total += i;
}
const selesai = performance.now();
console.log("tipe data :", typeof mulai);
console.log("naik      :", selesai >= mulai);
console.log("durasi    :", (selesai - mulai).toFixed(3), "ms");
console.log("hasil     :", total);

// 2. console.time / timeEnd: pasangan label yang dicatat runtime
console.time("jumlah-100rb");
let total2 = 0;
for (let i = 1; i <= 100000; i++) {
  total2 += i;
}
console.timeEnd("jumlah-100rb");
console.log("hasil     :", total2);