Suatu hari ada rekan yang bertanya di chat: “Gue nge-benchmark endpoint laporan, PR-nya 2x lebih cepat. Bisa di-review?” Teks itu disertai tautan PR dan satu baris angka. aku hampir menjawab ok sip. Tapi ada sesuatu yang mengganjal sejak aku mulai sering berurusan dengan benchmark: angka tanpa konteks hampir tidak punya arti.
“2x lebih cepat dibanding apa? Diukur di mana? Datanya sebesar apa? Workload-nya seperti apa?” Pertanyaan-pertanyaan itu bukan bentuk tidak percaya, melainkan cara membaca hasil benchmark yang benar. Artikel ini tentang apa yang aku pelajari soal hal itu: bahwa benchmark adalah alat bantu mengambil keputusan, bukan alat untuk memenangkan argumen dengan angka.
Table of contents
Open Table of contents
- Benchmark Itu Alat Keputusan, Bukan Lomba Angka
- Studi Kasus: Dua Pendekatan untuk Endpoint yang Lambat
- Cara Membaca Hasil Benchmark
- Angka Tanpa Konteks Bisa Menyesatkan
- Dari Angka ke Keputusan Bisnis
- Trade-off dalam Studi Kasus Kita
- Checklist Sebelum Percaya pada Angka Benchmark
- Penutup: Yang aku Pelajari
Benchmark Itu Alat Keputusan, Bukan Lomba Angka
Sebelum menjalankan benchmark apa pun, pertanyaan pertama yang sekarang selalu aku tanyakan adalah: keputusan apa yang ingin aku ambil dari angka ini?
Mau pakai library A atau B? Mau tambah index atau tulis ulang query? Mau pindah ke cache atau cukup tuning? Mau beli instance lebih besar atau optimasi kode dulu? Semua itu keputusan dengan konsekuensi nyata: waktu pengembangan, biaya infrastruktur, risiko, dan beban maintenance jangka panjang.
Kalau hasil benchmark tidak akan mengubah keputusan apa pun, benchmark itu sebenarnya tidak perlu. Dan kalau keputusannya sudah jelas, kita juga langsung tahu data apa yang harus dikumpulkan. Pertanyaan menentukan apa yang diukur — bukan sebaliknya.
Studi Kasus: Dua Pendekatan untuk Endpoint yang Lambat
aku pakai contoh yang sering muncul: endpoint laporan yang terasa lambat. Misalkan ada endpoint rekap penjualan bulanan, dan pemakai utamanya adalah tim finance di awal bulan. Pada jam ramai, p95-nya sekitar 1,8 detik. Dua pendekatan muncul dari tim:
- Pendekatan A: tambah index dan tulis ulang query supaya SELECT membaca lebih sedikit baris.
- Pendekatan B: hitung hasilnya di muka dan simpan, karena datanya hanya berubah beberapa kali seminggu. Endpoint tinggal membaca hasil yang sudah jadi.
aku jalankan benchmark sederhana menggunakan hey untuk mengirim banyak request dalam waktu bersamaan:
# Kirim 5000 request, 50 request berjalan bersamaan
hey -n 5000 -c 50 https://api.example.test/rekap-penjualan
Angka yang muncul kira-kira seperti ini:
Semua angka dalam artikel ini adalah ilustrasi, bukan hasil benchmark sungguhan. aku sengaja tidak menyebut angka asli karena fokus artikel ini adalah cara membacanya, bukan angkanya.
| Pendekatan | p50 | p95 | p99 | Throughput |
|---|---|---|---|---|
| A. Index + query baru | 40 ms | 180 ms | 420 ms | ~120 req/s |
| B. Hasil precomputed | 6 ms | 15 ms | 35 ms | ~800 req/s |
Kalau hanya melihat tabel ini, jawabannya terlihat jelas: B menang telak, p50-nya sekitar 7x lebih cepat dan p99-nya nyaris 12x, dengan throughput hampir 7x lipat. Tapi keputusan belum bisa diambil. Masih banyak konteks yang belum terjawab.
Cara Membaca Hasil Benchmark
Baseline dan Environment
Di mana angka itu diukur? Laptop developer dengan 16 GB RAM dan database lokal berisi 10 ribu baris tidak mewakili instance produksi dengan resource berbeda dan 40 juta baris. Kalau aku mengklaim “endpoint ini 2x lebih cepat”, environment pengukurannya harus setidaknya mirip dengan environment yang ingin aku klaim. Kalau tidak, yang aku ukur sebenarnya adalah perbedaan hardware — bukan perbedaan kode.
aku pernah melihat klaim “optimasi 100x” yang ternyata hasil perbandingan dengan query yang memang salah tulis sejak awal. Itu bukan benchmark, itu perbaikan bug yang sedang dirayakan sebagai optimasi.
Workload yang Mewakili
Ingin tahu perilaku endpoint saat dipakai banyak user bersamaan, tapi diukur dengan satu request berurutan? Hasilnya hanya bercerita tentang skenario paling sepi. Workload harus mendekati pola pemakaian asli: seberapa sering endpoint dipanggil, berapa banyak yang bersamaan, apakah ada cache yang ikut panas, dan apakah datanya membesar seiring waktu.
Antipattern yang masih sering terjadi:
# Satu request berurutan memberi satu angka tanpa distribusi dan tanpa konteks konkurensi
curl -w "waktu total: %{time_total}s\n" https://api.example.test/rekap-penjualan
curl seperti ini berguna untuk cek cepat, bukan untuk mengambil keputusan.
Rata-rata Menyembunyikan Ekor Panjang
Ini pelajaran yang paling sering aku temui. Rata-rata 200 ms terdengar enak. Tapi kalau p99-nya 3 detik, berarti satu dari seratus request mengalami 3 detik — dan pengalaman terburuk itu yang paling diingat pengguna. Keluhan biasanya lahir dari ekor panjang, bukan dari rata-rata.
Itu sebabnya aku hampir tidak pernah melihat rata-rata sendirian. aku melihat p50, p95, p99, dan throughput sekaligus. Satu angka rata-rata tidak cukup untuk membaca distribusi.
Ukur Hal yang Benar
aku pernah merasa puas setelah mengoptimalkan satu fungsi sampai 5x lebih cepat. Baru setelah dihitung ulang, fungsi itu ternyata hanya menyumbang 2% dari total waktu request — yang mendominasi justru query dan serialisasi di luar fungsi tersebut.
Mengukur handler saja berbeda dengan mengukur jalur end-to-end. Kalau tujuannya memperbaiki pengalaman pengguna, ukurlah jalur yang pengguna rasakan. Kalau tidak, kita bisa menghabiskan seminggu untuk mengoptimalkan bagian yang tidak menyumbang masalah.
Variansi dan Pemanasan
Satu kali run belum cukup. Angka pertama (cold) bisa jauh berbeda dari angka setelah aplikasi panas dan cache terisi. aku biasanya menjalankan beberapa kali, melihat sebarannya, dan mengambil median — bukan angka terbaik yang kebetulan muncul sekali. Melaporkan best case saja sama saja dengan memilih data yang mendukung jawaban yang kita inginkan.
Angka Tanpa Konteks Bisa Menyesatkan
Beberapa pola yang membuat angka benchmark menyesatkan:
- Klaim multiplikatif tanpa baseline. “2x lebih cepat” tidak bisa dievaluasi kalau baseline-nya tidak diketahui. Dua kali dari 5 ms tetap kecil; dua kali dari 800 ms bisa besar.
- Mikrobenchmark di luar jalur nyata. Fungsi yang tidak dominan dioptimalkan sampai 5x, tapi total request hanya membaik 1%. Angkanya benar, keputusannya salah.
- Menggeser biaya, bukan menghilangkan. Index membuat SELECT lebih cepat tapi menambah beban write dan storage. Cache membuat baca cepat tapi menambah memori dan kompleksitas invalidasi. Total biaya sistem tidak berkurang — bisa jadi hanya pindah tempat.
- Mengambil angka terbaik sebagai klaim. Hasil yang dilaporkan seharusnya jujur terhadap sebarannya, bukan menyembunyikan variansi supaya terlihat impresif.
Dari Angka ke Keputusan Bisnis
Di sinilah benchmark bertemu bisnis. Latensi, throughput, dan biaya baru masuk akal ketika dihubungkan dengan dampak yang mereka hasilkan.
Pengalaman Pengguna
p99 1,8 detik untuk laporan finance yang dibuka sekali sebulan — tidak nyaman, tapi bisa diterima. Kalau endpoint yang sama dipakai tim sales sebagai dashboard setiap beberapa menit, 1,8 detik terasa menyakitkan. Angka yang sama, dampak yang berbeda.
Pertanyaan yang harus dijawab bukan “berapa angkanya”, tapi “seberapa sering dan dalam situasi apa angka itu dirasakan”.
Biaya Infrastruktur
Pendekatan B memang jauh lebih cepat, tapi butuh penyimpanan untuk hasil yang dihitung di muka dan mekanisme untuk memperbaruinya. Kalau hasilnya memungkinkan turun dari 4 instance ke 2, itu keputusan bisnis yang nyata. Kalau tidak — dan trafiknya kecil — kecepatan ekstra B tidak membayar ongkosnya sendiri.
Effort Pengembangan dan Maintainability
Index plus query baru: perubahan kecil, mudah direview, risiko rendah. Hasil precomputed: ada logika invalidasi, sinkronisasi dengan sumber data, dan kode baru yang harus dites serta dirawat. Effort itu bukan biaya sekali jalan — setiap kali business rule berubah, kode ini ikut berubah. Sering kali solusi yang “paling cepat” justru paling mahal untuk dirawat.
Selain itu, setiap minggu yang dihabiskan untuk optimasi adalah minggu yang tidak dipakai untuk fitur. Keputusan mengoptimalkan seharusnya sejelas keputusan menambah fitur.
Trade-off dalam Studi Kasus Kita
Kembali ke dua pendekatan tadi. Keputusan terbaik bergantung pada konteks:
| Skenario | Yang lebih masuk akal | Alasan |
|---|---|---|
| Laporan dibuka sekali bulan, data jarang berubah | A (query + index) | Cukup cepat, perubahan kecil, tidak ada risiko data basi |
| Dashboard real-time yang dipakai terus-menerus | B (precomputed / cache) | Kecepatan dan throughput memang dibutuhkan, biaya ekstra terbayar |
| Trafik kecil, tapi data membesar cepat | A dulu, B belakangan | Mulai dari yang murah, baru investasi ketika data benar-benar menuntut |
Tidak ada jawaban yang selalu benar. Yang penting bukan “pendekatan mana yang menghasilkan angka terkecil”, tapi “pendekatan mana yang paling masuk akal untuk skenario kita”. Benchmark membantu membaca skenario; keputusannya tetap milik kita.
Checklist Sebelum Percaya pada Angka Benchmark
Sekarang, setiap kali melihat hasil benchmark — milik sendiri atau orang lain — aku memeriksa hal ini:
- Keputusan apa yang mau diambil dari angka ini?
- Diukur di environment mana, dengan data dan workload seperti apa?
- Apakah angkanya mencakup p50/p95/p99 dan throughput, bukan cuma rata-rata?
- Apakah ini mengukur jalur yang benar-benar dirasakan (end-to-end)?
- Berapa ongkos dari solusi yang terlihat unggul — effort, infrastruktur, maintenance?
- Kalau angka tidak mengubah keputusan, untuk apa benchmark dilakukan?
Penutup: Yang aku Pelajari
Benchmark bukan lomba angka. Hasil yang paling kecil belum tentu paling bijak untuk dipilih, dan angka yang paling besar belum tentu tanda masalah. Semuanya tergantung konteks dan ongkos.
Yang paling aku pelajari bukan cara membaca grafik atau tools yang lebih canggih, melainkan cara mengajukan pertanyaan. Benchmark yang baik bukan yang menghasilkan angka paling kecil, tapi yang menghasilkan kejelasan: apa yang sedang diukur, siapa yang merasakannya, dan apa yang harus aku putuskan. Sisanya — angka, tabel, grafik — hanyalah alat bantu.