SearchValues akhirnya menunjukkan keunggulan yang terukur di .NET 10 saat memindai buffer besar untuk delimiter yang jarang, dengan SearchValues selesai dalam 3,3 ms dibandingkan dengan IndexOfAny yang memakan waktu 5,6 ms pada payload sebesar 32 MB.

Mengapa SearchValues muncul

.NET 8 memperkenalkan SearchValues untuk menghitung sebelumnya (pre-compute) sekumpulan karakter (atau byte) dan membiarkan runtime memilih algoritma pemindaian tercepat untuk set tersebut. Buat objeknya sekali, lalu gunakan kembali kapan pun Anda perlu menemukan salah satu nilai dalam sebuah span. Runtime dapat menggunakan instruksi vektorisasi, loop tanpa percabangan (branch-free loops), atau trik tingkat rendah lainnya yang tidak dapat ditandingi oleh alternatif buatan tangan tanpa upaya besar.

Benchmark yang penting

Pengujian yang memicu diskusi ini menggunakan buffer 32 MB yang berisi lima karakter delimiter. Tiga pendekatan diukur waktunya pada .NET 10:

  • IndexOfAny(char[]) – 10,2 ms
  • Loop foreach manual pada span – 19,4 ms
  • SearchValues – 9,7 ms

SearchValues mengalahkan IndexOfAny bawaan hanya dengan selisih setengah milidetik. Hasilnya bukanlah klaim dramatis "lima kali lebih cepat" yang beredar di forum; .NET modern sudah mengoptimalkan IndexOfAny untuk set kecil, sehingga mempersempit celah tersebut.

Ketika delimiter jarang muncul—muncul sekali setiap 40 KB alih-alih setiap 60 byte—gambaran tersebut berubah:

  • IndexOfAny(char[]) – 5,6 ms
  • SearchValues – 3,3 ms

Sekarang SearchValues 1,7 × lebih cepat karena engine melesat melalui rangkaian panjang data yang tidak cocok dengan langkah-langkah vektorisasi, sementara IndexOfAny beralih ke jalur yang kurang agresif.

Biaya tersembunyi

SearchValues tidaklah gratis. Mengonstruksi objek tersebut mengalokasikan memori dan membangun tabel pencarian (lookup tables) internal. Jika Anda menginstansiasinya pada setiap pemanggilan metode, overhead-nya akan jauh melampaui keuntungan runtime apa pun. Sebuah benchmark yang memanggil rutinitas pemindaian satu juta kali pada baris-baris pendek menunjukkan:

  • SearchValues statis (digunakan kembali) – total 25,1 ms
  • SearchValues per-pemanggilan – total 70,2 ms

Membuat objek per pemanggilan membuat seluruh operasi tiga kali lebih lambat dibandingkan jika tidak menggunakan SearchValues sama sekali. Simpan instansnya dalam field static readonly atau gunakan kembali di berbagai pemanggilan.

Kapan harus menggunakan SearchValues

  • Input besar, sedikit kecocokan – Jalur vektorisasi sangat unggul ketika pemindai dapat melompati rentang panjang tanpa mengenai delimiter.
  • Pemindaian berulang dengan set yang sama – Jika karakter yang sama dicari berkali-kali, pengaturan satu kali di awal akan sangat menguntungkan.

Kapan tetap menggunakan IndexOfAny

  • String pendek atau banyak kecocokan – Biaya pengaturan tambahan lebih besar daripada keuntungan kecepatan yang marginal.
  • Kode yang sudah menggunakan IndexOfAny – Implementasi .NET modern sudah sangat dioptimalkan untuk set karakter kecil, sehingga menggantinya dengan SearchValues mungkin tidak akan memberikan perbedaan signifikan.

Kesalahan umum

  • Menyisipkan konstruksi di dalam hot loop – Menyebabkan perlambatan tiga kali lipat seperti yang ditunjukkan di atas.
  • Mencoba untuk "mengakali" runtime dengan loop manual – Versi foreach manual dua kali lebih lambat daripada kedua metode bawaan, mengonfirmasi bahwa library .NET sulit dikalahkan tanpa pengetahuan mendalam tentang instruksi SIMD.
  • Mengasumsikan peningkatan kecepatan universal – Kemenangan setengah milidetik pada data padat membuktikan bahwa SearchValues bukanlah kode curang universal; manfaatnya bergantung pada data.

Kesimpulan

SearchValues memberikan keuntungan yang jelas hanya saat Anda memindai buffer besar untuk karakter yang jarang muncul dan mampu menanggung biaya konstruksi satu kali. Untuk mayoritas skenario pencarian string sehari-hari—input pendek, kecocokan yang sering, atau kode yang sudah mengandalkan IndexOfAny—metode bawaan tetap menjadi pilihan yang lebih sederhana dan lebih cepat. Gunakan SearchValues secara selektif, simpan (cache) instansnya, dan Anda akan menghindari penalti tersembunyi sambil mendapatkan keuntungan performa yang nyata.

Kode sumber dan rangkaian pengujian lengkap: https://dev.to/ssukhpinder/when-searchvalues-actually-pays-off-310l