Belajar Fzf - Performance & Dataset Besar
Series/Belajar Fzf/Episode 17
Episode 17 of 23

Belajar Fzf - Performance & Dataset Besar

Mengoptimalkan kecepatan fzf pada dataset besar: memilih algoritma dengan --algo, membatasi item sebelum masuk, keputusan --sort, dan meringankan beban preview. Termasuk peningkatan performa fzf modern yang skalanya linear antar core CPU, pengurangan jejak cache memori, serta strategi praktis menangani jutaan item.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Di episode 16 kalian membuat daftar fzf menjadi hidup — reload berkala, query yang diteruskan ke ripgrep, dan bahkan kendali dari proses eksternal lewat --listen. Semua itu terasa ajaib ketika daftarnya seribu baris. Tetapi apa yang terjadi ketika daftarnya satu juta baris? Di sinilah pertanyaan sejati tentang fzf dimulai: seberapa cepat ia bisa menyaring, dan bagaimana kita menjaganya tetap cepat.

Episode ini membahas performa fzf dari dua sisi. Sisi yang bisa kalian kendalikan: memilih algoritma dengan --algo, membatasi jumlah item sebelum masuk, keputusan --sort, dan meringankan beban preview. Sisi yang datang dari pengembang: kemampuan fzf modern yang skalanya linear antar core CPU dan pengurangan drastis jejak cache memori sejak 0.71 — plus strategi praktis menangani dataset berukuran jutaan.

Prinsip pertama yang harus dipahami: fzf adalah filter yang berjalan dalam pipeline, dan pipeline hanya secepat komponen yang paling lambat. Daftar yang lambat dibuat di hulu tidak akan terselamatkan oleh fzf yang super cepat di hilir. Kinerja adalah tanggung jawab seluruh rantai, bukan hanya ujung yang terlihat.

Peta Kinerja fzf

Beban fzf terbagi dalam tiga tahap yang berjalan sebagian paralel:

  1. Membaca input — mengonsumsi baris-baris dari stdin secara asinkron.
  2. Mencocokkan (matching) — menyaring baris terhadap query; tahap yang paling boros CPU.
  3. Menampilkan dan preview — merender antarmuka dan menjalankan perintah preview.

Ketiganya tidak seimbang. Untuk daftar besar, matching mendominasi; untuk daftar kecil, preview sering kali justru yang paling lambat. Mengoptimalkan berarti tahu di tahap mana waktu kalian terbakar, bukan sekadar menyalakan semua opsi "cepat" sekaligus.

Pilih Algoritma: --algo

fzf menyediakan dua algoritma pencocokan fuzzy. v2 adalah default — algoritma optimal scoring yang menghasilkan kualitas ranking terbaik. v1 adalah algoritma gaya lama (seperti yang dipakai fzy) yang lebih sederhana, dengan trade-off kualitas ranking yang lebih kasar.

Memilih algoritma pencocokan
fzf --algo v2
fzf --algo v1
v2 default dengan skor optimal; v1 lebih sederhana

Note

--algo menentukan kualitas ranking, bukan sekadar kecepatan. v2 memilih hasil yang paling relevan ketika banyak item cocok dengan skor dekat; v1 lebih mudah "salah urutan" pada daftar besar. Mulailah dari v2 (default) dan turun ke v1 hanya jika pengukuran kalian menunjukkan bahwa scoring bukan bottleneck — jangan menurunkan kualitas tanpa data.

Batasi Item Sebelum Masuk

Aturan pertama dataset besar: jangan kirim lebih dari yang dibutuhkan. Setiap baris yang masuk fzf harus disimpan, diindeks, dan berpotensi di-scoring. Baris yang tidak pernah akan kalian pilih hanyalah sampah yang membuat segalanya lambat.

Dua cara yang paling efektif: batasi sumbernya (filter di hulu dengan fd atau rg, bukan find), dan pangkas ukurannya (head) ketika kalian hanya peduli pada bagian awal:

Batasi daftar sebelum masuk ke fzf
fd -t f . ~ | head -n 5000 | fzf
head memangkas daftar; fd lebih cepat dari find pada traversal
Hanya ekor log yang besar
tail -f /var/log/app.log | fzf --tail 100000 --tac --no-sort --exact
--tail memuat N baris terakhir dari aliran tak berujung

Contoh kedua ini memakai fitur --tail: dari aliran log yang tidak pernah berakhir, fzf hanya menyimpan 100.000 baris terakhir — daftar tetap terbatas meski sumbernya tak berujung.

Keputusan --sort

Sorting adalah salah satu operasi paling mahal di fzf. Secara default (--sort), fzf mengurutkan hasil berdasarkan skor kecocokan. Ketika daftar raksasa dan urutan sudah bermakna — history yang ingin tetap kronologis, log yang ingin tetap berurutan — --no-sort menghapus biaya itu dan mempertahankan urutan input apa adanya:

Sorting hasil
seq 1000000 | fzf --sort
seq 1000000 | fzf --no-sort
--sort default mengurutkan berdasar skor; --no-sort mempertahankan urutan input

Untuk hasil imbang pada --sort, --tiebreak menentukan kriteria pembeda. Pada dataset besar, kombinasi --no-sort --exact adalah jalan pintas yang sah: item tetap disaring, tetapi pekerjaan scoring yang berat dilewati.

Tip

Ukur sebelum memilih. time adalah sahabat kalian: bandingkan seq 1000000 | fzf --sort < /dev/null dengan versi --no-sort dan lihat perbedaannya di mesin kalian sendiri. Optimalisasi tanpa pengukuran hanyalah dugaan yang tampak ilmiah.

Minimalkan Beban Preview

Ketika daftar sudah besar, sering kali yang terasa lambat bukan filter-nya melainkan preview. Setiap kali kursor berpindah, perintah preview dijalankan ulang. Tiga penyesuaian yang paling berdampak:

  1. Gunakan perintah murah. head dan sed jauh lebih ringan daripada tool yang mem-parse seluruh file.
  2. Matikan pemrosesan yang tidak perlu. bat dengan --style=plain dan tanpa --color=always menghindari kerja parsing warna.
  3. Batasi ruang lingkup. --preview-window yang kecil dan perintah yang hanya membaca beberapa baris membatasi kerja per perpindahan.
Preview yang ringan
fzf --preview 'head -n 30 {}'
fzf --preview 'bat --style=plain {}'
head membatasi baris; gaya tanpa warna mengurangi parsing

Kinerja Modern: Linear di Core CPU

Sekarang mari ke sisi pengembang. Sejak fzf 0.71, kinerja pencarian fzf menjadi scalable secara linear di seluruh core CPU: pekerjaan matching dibagi ke semua inti prosesor yang tersedia, sehingga daftar yang sama dua kali lebih besar tidak berarti waktu dua kali lipat jika ada core untuk dikerjakan. Ini berbeda dari versi lama yang sebagian besar berjalan pada satu inti.

Dampak praktisnya: pada mesin multicore modern, fzf memfilter ratusan ribu hingga jutaan baris dengan latensi yang tidak lagi terasa — selama data melewatinya secara streaming, bukan menunggu seluruh input terkumpul.

Jejak Memori: Cache yang Lebih Ringan

Bersamaan dengan itu, rilis 0.71 mencatat pengurangan 86x pada jejak cache memori per entri. Angka besar itu berasal dari penyimpanan yang hemat: cache hasil pencocokan kini menyimpan indeks yang jauh lebih kecil daripada sebelumnya, sehingga daftar dengan jutaan item bisa ditampung dalam memori yang jauh lebih hemat — dan cache yang lebih kecil juga berarti lebih ramah untuk cache CPU itu sendiri, mempercepat iterasi pencarian berulang.

Bagi kalian, ini bukan sekadar angka: ini berarti jutaan item kini masuk akal untuk diproses di laptop tanpa membuat swap berbunyi.

Strategi untuk Jutaan Item

Merangkum semuanya ke dalam resep yang bisa dijalankan, berikut strategi untuk dataset berukuran jutaan:

StrategiKenapaCara
Filter di huluKurangi baris yang masukGunakan rg/fd, bukan find
Pertahankan urutanHindari biaya sorting--no-sort pada input yang sudah terurut
Lewati scoring beratKurangi kerja matching--exact bila kecocokan presisi sudah cukup
Batasi daftarJaga memori tetap wajar--tail untuk aliran, head untuk awal daftar
Streaming, bukan menungguTampil sebelum semua input tibaJangan cat file | fzf dengan file yang bisa dipipakan live
Normalisasi di huluKurangi parsing di dalam fzfBuang ANSI, kolom berlebih, dan baris kosong sebelum masuk

Important

Satu perangkap yang sering menjatuhkan orang: fzf menampilkan antarmuka sebelum seluruh input selesai dibaca — itu memang dirancang begitu. Tetapi jika kalian memaksa sinkronisasi dengan --sync, fzf menunggu hingga input dan pencarian awal selesai sebelum menggambar. Pada daftar jutaan baris, --sync membuat layar tampak "beku" selama beberapa detik. Gunakan --sync hanya ketika aksi awal (seperti start) memang harus melihat daftar lengkap.

Kesalahan Umum

KesalahanGejalaSolusi
Mengirim jutaan baris tanpa filterLambat sejak pembacaan inputFilter di hulu dengan rg/fd
--sort pada input yang sudah terurutBiaya sorting tak berguna--no-sort mempertahankan urutan input
Preview mahal tiap perpindahan kursorTerasa lambat walau filter cepathead/sed, bat --style=plain, batasi preview
--sync pada daftar raksasaLayar "beku" di awalLepas --sync; biarkan fzf streaming
ANSI berlebihan dalam itemOverhead parsing warnaBuang escape sequence di hulu
Mengubah --algo tanpa ukurKualitas menurun tanpa keuntunganUkur dengan time dulu, baru putuskan

Caution

Optimalisasi terbaik adalah yang berangkat dari pengukuran: time untuk pipeline, --no-sort --exact untuk uji cepat, dan observasi terhadap preview yang paling sering dipicu. Fzf 0.71 telah memindahkan banyak beban berat ke parallelisme dan cache yang hemat — tugas kalian bukan berlomba dengannya, melainkan tidak menghalangi jalannya.

Penutup

Pada episode 17 ini kalian melengkapi sisi performa fzf: memilih algoritma dengan --algo (v2 default, v1 untuk kebutuhan khusus), membatasi item sebelum masuk dengan fd, head, dan --tail, memutuskan --sort versus --no-sort berdasarkan makna urutan input, serta meringankan beban preview dengan perintah murah dan gaya tanpa warna. Kalian juga memahami peningkatan fzf modern — pencarian yang scalable linear antar core CPU dan cache memori yang 86x lebih ringan sejak 0.71 — beserta strategi untuk menangani jutaan item secara streaming.

Pesan untuk dibawa pulang: kecepatan fzf adalah hasil kerja sama antara hulu yang hemat dan hilir yang efisien. Dataset yang dibatasi dengan baik masuk ke mesin yang dipercepat dengan baik — itulah resepnya.

Kini kalian punya bekal lengkap untuk memakai fzf dengan benar. Tetapi bahkan setup terbaik kadang tidak berjalan sesuai harapan — prompt aneh, hasil yang tidak muncul, preview yang diam. Di episode 18 kita membahas troubleshooting & debugging: menyalakan --debug, memahami log internal, dan mendiagnosis masalah yang paling sering muncul di lapangan.