Mengapa egrep [wW] [oO] [rR] [dD] lebih cepat dari grep -i word?

49

Saya telah menggunakan grep -ilebih sering dan saya menemukan bahwa itu lebih lambat daripada yang egrepsetara, di mana saya cocok dengan huruf besar atau kecil dari setiap huruf:

$ time grep -iq "thats" testfile

real    0m0.041s
user    0m0.038s
sys     0m0.003s
$ time egrep -q "[tT][hH][aA][tT][sS]" testfile

real    0m0.010s
user    0m0.003s
sys     0m0.006s

Apakah grep -imelakukan tes tambahan yang egreptidak?

tildearrow
sumber
12
Coba yang grepsebaliknya, untuk memastikan Anda tidak mengukur perbedaan antara cache disk dari flie.
EightBitTony
3
Saya telah menerima file sebelum pengujian, jadi ini di-cache. Waktu yang hampir sama jika dilakukan dalam urutan terbalik.
tildearrow
21
Ini dapat bergantung pada lokal: beberapa lokal melibatkan perhitungan rumit untuk menjelaskan ketidaksensitifan kasus. GNU grep sangat lambat dalam banyak situasi yang melibatkan Unicode. Pengaturan lokal apa yang Anda gunakan? Di bawah varian apa Unix? Apa isi file tes Anda?
Gilles 'SO- stop being evil'
6
@Gilles terlihat bagus, mengulangi setiap tes di sini 100 kali (menghitung semuanya), egreplebih cepat daripada grepsampai saya mengatur LANG=Cdan kemudian mereka berdua kira-kira sama.
EightBitTony
2
@EightBitTony Lihat userwaktu (yang tidak termasuk waktu menunggu disk). Ada urutan besarnya perbedaan.
kasperd

Jawaban:

70

grep -i 'a'setara dengan grep '[Aa]'lokal ASCII saja. Di lokal Unicode, persamaan karakter dan konversi bisa rumit, jadi grepmungkin harus melakukan pekerjaan ekstra untuk menentukan karakter yang setara. Pengaturan lokal yang relevan adalah LC_CTYPE, yang menentukan bagaimana byte diartikan sebagai karakter.

Dalam pengalaman saya, GNU grepbisa lambat ketika dipanggil di lokal UTF-8. Jika Anda tahu bahwa Anda sedang mencari karakter ASCII saja, memintanya dalam lokal ASCII saja mungkin lebih cepat. saya mengharapkan itu

time LC_ALL=C grep -iq "thats" testfile
time LC_ALL=C egrep -q "[tT][hH][aA][tT][sS]" testfile

akan menghasilkan timing yang tidak bisa dibedakan.

Yang sedang berkata, saya tidak bisa mereproduksi temuan Anda dengan GNU grepdi Debian jessie (tetapi Anda tidak menentukan file tes Anda). Jika saya menetapkan lokal ASCII ( LC_ALL=C), grep -ilebih cepat. Efeknya tergantung pada sifat tepat dari string, misalnya string dengan karakter yang diulang mengurangi kinerja ( yang diharapkan ).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Penulis menggunakan Ubuntu 14.04 yang dikirimkan dengan grep 2.10. Kecepatan pertandingan yang tidak peka huruf besar-kecil ( -i) dengan lokal multibyte seharusnya meningkat pada 2.17 .
Lekensteyn
@Lekensteyn Bagus untuk tahu, terima kasih. Ubuntu 14.04 sebenarnya hadir dengan grep 2.16, tapi itu juga pra-2.17; Saya diuji dengan grep 2.20, yang menjelaskan mengapa saya tidak melihat perlambatan yang sama.
Gilles 'SANGAT berhenti menjadi jahat'
Benar, saya melihat rilis LTS yang salah, Ubuntu 12.04 dikirimkan dengan grep 2.10 sedangkan Ubuntu 14.04 menyertakan grep 2.16.
Lekensteyn
1
Saya cukup yakin itu grep -i 'a'setara dengan grep '[Aa]'di daerah mana pun. Contoh yang tepat adalah grep -i 'i'yang mana grep '[Ii]'atau grep '[İi]'(Huruf I dengan titik di atas, U + 130, lokal Turki). Namun, tidak ada cara yang efisien untuk grepmenemukan kelas kesetaraan ini diberikan lokal.
MSalters
15

Karena penasaran, saya menguji ini pada sistem Arch Linux:

$ uname -r
4.4.5-1-ARCH
$ df -h .
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           3.9G  720K  3.9G   1% /tmp
$ dd if=/dev/urandom bs=1M count=1K | base64 > foo
$ df -h .                                         
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           3.9G  1.4G  2.6G  35% /tmp
$ for i in {1..100}; do /usr/bin/time -f '%e' -ao grep.log grep -iq foobar foo; done
$ for i in {1..100}; do /usr/bin/time -f '%e' -ao egrep.log egrep -q '[fF][oO][oO][bB][aA][rR]' foo; done

$ grep --version
grep (GNU grep) 2.23
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.

Dan kemudian beberapa statistik dari Apakah ada cara untuk mendapatkan min, maks, median, dan rata-rata daftar angka dalam satu perintah? :

$ R -q -e "x <- read.csv('grep.log', header = F); summary(x); sd(x[ , 1])"
> x <- read.csv('grep.log', header = F); summary(x); sd(x[ , 1])
       V1       
 Min.   :1.330  
 1st Qu.:1.347  
 Median :1.360  
 Mean   :1.362  
 3rd Qu.:1.370  
 Max.   :1.440  
[1] 0.02322725
> 
> 
$ R -q -e "x <- read.csv('egrep.log', header = F); summary(x); sd(x[ , 1])"
> x <- read.csv('egrep.log', header = F); summary(x); sd(x[ , 1])
       V1       
 Min.   :1.330  
 1st Qu.:1.340  
 Median :1.360  
 Mean   :1.365  
 3rd Qu.:1.380  
 Max.   :1.430  
[1] 0.02320288
> 
> 

Aku ada di en_GB.utf8tempat itu, tetapi waktunya hampir tidak bisa dibedakan.

muru
sumber