Utilitas pengindeks ugrep mengindeks file secara rekursif untuk mempercepat pengambilan rekursif.
Isi arsip dan file terkompresi juga diindeks ketika ditentukan dengan opsi baris perintah. Hal ini menghilangkan pencarian ketika tidak ada konten yang cocok dengan pola yang ditentukan.
ugrep adalah pencari file cepat yang kompatibel dengan grep dan mendukung pencarian berbasis indeks. Pencarian berbasis indeks bisa jauh lebih cepat pada sistem file yang lambat dan ketika caching sistem file tidak efektif: jika sistem file pada drive yang dicari tidak di-cache dalam RAM, yaitu "dingin", maka pengindeksan akan mempercepat pencarian. Itu hanya mencari file-file yang mungkin cocok dengan pola regex tertentu dengan menggunakan indeks file. Indeks ini memungkinkan pemeriksaan cepat apakah ada potensi kecocokan, sehingga kami menghindari pencarian semua file.
Pencarian berbasis indeks dengan ugrep aman dan tidak pernah melewatkan file terbaru yang mungkin cocok. Jika ada file dan direktori yang ditambahkan atau diubah setelah pengindeksan, maka pencarian akan selalu mencari penambahan dan perubahan yang dilakukan pada sistem file dengan membandingkan stempel waktu file dan direktori dengan stempel waktu pengindeksan.
Ketika banyak file ditambahkan atau diubah setelah pengindeksan, maka kita mungkin ingin mengindeks ulang untuk memperbarui indeks. Pengindeksan ulang bersifat bertahap, sehingga tidak memerlukan waktu sebanyak proses pengindeksan awal.
Contoh umum namun kecil dari pencarian berbasis indeks, misalnya pada repositori ugrep v3.12.6 yang ditempatkan pada drive terpisah:
$ cd drive/ugrep
$ ugrep-indexer -I
12247077 bytes scanned and indexed with 19% noise on average
1317 files indexed in 28 directories
28 new directories indexed
1317 new files indexed
0 modified files indexed
0 deleted files removed from indexes
128 binary files ignored with --ignore-binary
0 symbolic links skipped
0 devices skipped
5605227 bytes indexing storage increase at 4256 bytes/file
Pencarian normal pada sistem file dingin tanpa pengindeksan memerlukan waktu 1,02 detik setelah melepas drive
dan memasangnya kembali untuk menghapus cache FS guna mencatat efek pengindeksan:
$ ugrep -I -l 'std::chrono' --stats
src/ugrep.cpp
Searched 1317 files in 28 directories in 1.02 seconds with 8 threads: 1 matching (0.07593%)
Ripgrep 13.0.0 membutuhkan waktu lebih lama yaitu 1,18 detik untuk pencarian dingin yang sama (ripgrep melewatkan file biner secara default, jadi opsi -I
tidak ditentukan):
$ time rg -l 'std::chrono'
src/ugrep.cpp
1.18 real 0.01 user 0.06 sys
Sebaliknya, dengan pengindeksan, pencarian sistem file dingin hanya membutuhkan 0,0487 detik dengan ugrep, yang 21 kali lebih cepat, setelah melepas drive
dan memasangnya lagi untuk menghapus cache FS guna mencatat efek pengindeksan:
$ ugrep --index -I -l 'std::chrono' --stats
src/ugrep.cpp
Searched 1317 files in 28 directories in 0.0487 seconds with 8 threads: 1 matching (0.07593%)
Skipped 1316 of 1317 files with non-matching indexes
Selalu ada beberapa variasi dalam waktu yang berlalu dengan 0,0487 detik merupakan waktu terbaik dari empat proses pencarian yang menghasilkan rentang waktu pencarian dari 0,0487 (peningkatan kecepatan 21x) hingga 0,0983 detik (peningkatan kecepatan 10x).
Peningkatan kecepatan secara umum mungkin jauh lebih tinggi dibandingkan dengan demo kecil ini, tergantung pada beberapa faktor, ukuran file yang diindeks, kecepatan baca sistem file dan asumsi sebagian besar file dingin.
Algoritme pengindeksan yang saya rancang terbukti monoton : akurasi yang lebih tinggi menjamin peningkatan kinerja pencarian dengan mengurangi tingkat positif palsu, tetapi juga meningkatkan overhead penyimpanan indeks. Demikian pula, akurasi yang lebih rendah menurunkan kinerja pencarian, namun juga mengurangi overhead penyimpanan indeks. Oleh karena itu, saya menamai pengindeks saya dengan pengindeks monotonik .
Jika ruang penyimpanan file sangat mahal, maka kita dapat mengurangi overhead penyimpanan indeks dengan menentukan akurasi pengindeksan yang lebih rendah.
Mengindeks contoh dari atas dengan level 0 (opsi -0
) mengurangi overhead penyimpanan pengindeksan sebanyak 8,6 kali, dari 4256 byte per file menjadi 490 byte per file:
12247077 bytes scanned and indexed with 42% noise on average
1317 files indexed in 28 directories
0 new directories indexed
1317 new files indexed
0 modified files indexed
0 deleted files removed from indexes
128 binary files ignored with --ignore-binary
0 symbolic links skipped
0 devices skipped
646123 bytes indexing storage increase at 490 bytes/file
Pencarian yang diindeks masih jauh lebih cepat 12x dibandingkan yang tidak diindeks untuk contoh ini, dengan 16 file yang benar-benar dicari (15 positif palsu):
Searched 1317 files in 28 directories in 0.0722 seconds with 8 threads: 1 matching (0.07593%)
Skipped 1301 of 1317 files with non-matching indexes
Pola regex yang lebih kompleks dari contoh ini mungkin memiliki tingkat positif palsu yang lebih tinggi secara alami, yaitu tingkat file yang dianggap mungkin cocok padahal sebenarnya tidak. Tingkat positif palsu yang lebih tinggi dapat mengurangi kecepatan pencarian ketika tingkat tersebut cukup besar untuk memberikan dampak.
Tabel berikut menunjukkan bagaimana akurasi pengindeksan memengaruhi penyimpanan pengindeksan dan rata-rata gangguan per file yang diindeks. Kolom paling kanan menunjukkan kecepatan pencarian dan tingkat positif palsu untuk ugrep --index -I -l 'std::chrono'
:
menurut. | penyimpanan indeks (KB) | kebisingan rata-rata | positif palsu | waktu pencarian |
---|---|---|---|---|
-0 | 631 | 42% | 15 | 0,0722 |
-1 | 1276 | 39% | 1 | 0,0506 |
-2 | 1576 | 36% | 0 | 0,0487 |
-3 | 2692 | 31% | 0 | unch |
-4 | 2966 | 28% | 0 | unch |
-5 | 4953 | 23% | 0 | unch |
-6 | 5474 | 19% | 0 | unch |
-7 | 9513 | 15% | 0 | unch |
-8 | 10889 | 11% | 0 | unch |
-9 | 13388 | 7% | 0 | unch |
Jika regex yang ditentukan cocok dengan lebih banyak kemungkinan pola, misalnya dengan penelusuran ugrep --index -I -l '(todo|TODO)[: ]'
, maka kita dapat mengamati tingkat positif palsu yang lebih tinggi di antara 1.317 file yang dicari, menghasilkan waktu pencarian yang sedikit lebih lama:
menurut. | positif palsu | waktu pencarian |
---|---|---|
-0 | 189 | 0,292 |
-1 | 69 | 0,122 |
-2 | 43 | 0,103 |
-3 | 19 | 0,101 |
-4 | 16 | 0,097 |
-5 | 2 | 0,096 |
-6 | 1 | unch |
-7 | 0 | unch |
-8 | 0 | unch |
-9 | 0 | unch |
Akurasi -4
adalah defaultnya (dari -5
sebelumnya di rilis lama), yang cenderung bekerja sangat baik untuk mencari dengan pola regex dengan kompleksitas sedang.
Satu kata peringatan. Selalu ada sedikit biaya tambahan untuk memeriksa indeks. Ini berarti bahwa jika semua file sudah di-cache di RAM, karena file baru saja dicari atau dibaca, maka pengindeksan tentu saja tidak akan mempercepat pencarian. Dalam hal ini, pencarian yang tidak diindeks mungkin lebih cepat. Selain itu, pencarian berbasis indeks memiliki waktu permulaan yang lebih lama. Waktu mulai ini bertambah ketika kelas karakter Unicode dan wildcard digunakan yang harus dikonversi ke tabel hash.
Ringkasnya, pencarian berbasis indeks paling efektif ketika mencari banyak file dingin dan ketika pola regex tidak terlalu cocok, misalnya kita ingin membatasi penggunaan pengulangan tak terbatas *
dan +
dan membatasi penggunaan kelas karakter Unicode ketika mungkin. Hal ini mengurangi waktu mulai ugrep dan membatasi tingkat kecocokan pola positif palsu (lihat juga Tanya Jawab di bawah).
Mengindeks semua file non-biner yang menunjukkan kemajuan secara rekursif dan bertahap:
ugrep-indexer -I -v
Secara rekursif dan bertahap mengindeks semua file non-biner, termasuk file non-biner yang disimpan dalam arsip dan file terkompresi, menunjukkan kemajuan:
ugrep-indexer -z -I -v
Secara bertahap mengindeks semua file non-biner, termasuk arsip dan file terkompresi, menunjukkan kemajuan, mengikuti tautan simbolik ke file (tetapi tidak ke direktori), tetapi jangan mengindeks file dan direktori yang cocok dengan gumpalan di .gitignore:
ugrep-indexer -z -I -v -S -X
Paksa pengindeksan ulang semua file non-biner, termasuk arsip dan file terkompresi, ikuti tautan simbolis ke file (tetapi tidak ke direktori), tetapi jangan mengindeks file dan direktori yang cocok dengan gumpalan di .gitignore:
ugrep-indexer -f -z -I -v -S -X
Sama, tetapi kurangi penyimpanan file indeks ke minimum dengan mengurangi akurasi pengindeksan dari 5 (default) menjadi 0:
ugrep-indexer -f -0 -z -I -v -S -X
Tingkatkan kinerja pencarian dengan meningkatkan akurasi pengindeksan dari 5 (default) menjadi 7 dengan mengorbankan file indeks yang lebih besar:
ugrep-indexer -f7zIvSX
Hapus semua file indeks ._UG#_Store
yang tersembunyi secara rekursif untuk memulihkan pohon direktori menjadi tidak terindeks:
ugrep-indexer -d
Konfigurasikan dan kompilasi dengan:
./build.sh
Jika diinginkan tetapi tidak diperlukan, instal dengan:
sudo make install
Tambahkan opsi untuk membuat satu file indeks, misalnya ditentukan secara eksplisit ke ugrep. Hal ini selanjutnya dapat meningkatkan kecepatan pencarian yang diindeks jika file indeks terletak pada sistem file yang cepat. Jika tidak, jangan mengharapkan banyak perbaikan atau bahkan kemungkinan perlambatan, karena satu file indeks tidak dapat dicari secara bersamaan dan lebih banyak entri indeks akan diperiksa padahal sebenarnya direktori dilewati (melewatkan indeksnya juga). Eksperimen akan membuktikannya. Peringatan penting dari pendekatan ini adalah bahwa pencarian berbasis indeks dengan ugrep --index
tidak lagi aman: file baru dan yang dimodifikasi yang belum diindeks tidak akan dicari.
Setiap filter N-gram Bloom memiliki "bit tier" sendiri di tabel hash untuk menghindari konflik hash. Misalnya 2 gram tidak berbagi bit apa pun dengan 3 gram. Hal ini memastikan bahwa kita tidak pernah mendapatkan hasil positif palsu dengan pencocokan karakter yang salah yang sebenarnya bukan bagian dari pola. Namun, ruang bit 1 gram (karakter tunggal) kecil (paling banyak 256 bit). Oleh karena itu, kami membuang beberapa bit ketika tabel hash lebih besar. Pendekatan yang mungkin dilakukan untuk mengurangi pemborosan adalah dengan menggabungkan 1 gram dengan 2 gram untuk berbagi ruang bit yang sama. Hal ini mudah dilakukan jika kita menganggap 1 gram sama dengan 2 gram dengan karakter kedua disetel ke