2012-12-03 24 views
7

Bu soru, this other one'den esinlenmiştir.Neden (bazen) yakalamadan daha hızlı görünüyor?

s/,(\d)/$1/ - s/,(?=\d)// karşılaştırması: eski, virgül değil, yalnızca rakamı değiştirmek için bir yakalama grubunu kullanır; bu, virgülün bir basamakla başarılı olup olmadığını belirlemek için bir görünüm kullanır. İkinci neden bazen this answer'da tartışıldığı gibi daha hızlıdır?

+1

Gerçekten da önemli bir fark belirleyemez. İkisi de çok hızlı. Bu regex'lere, yakalamaya değil de benzerlere uygulanır. – TLP

+4

Apaçık: verileri kopyalamak için grup kuvvetini yakalayın ve sonra da '$ 1' değerindeki enterpolasyonu değiştirin, ikinci regex ise sadece bul/kontrol et/kaldır. Bununla birlikte, hızdaki fark görünmez olmalıdır. – PSIAlt

cevap

4

İki yaklaşım farklı şeyler yapar ve farklı türde genel masraflara sahiptir. Yakaladığınızda, perl yakalanan metnin bir kopyasını çıkarmak zorundadır. Tüketmeden maç öncesi maçlar; başladığı yeri işaretlemek zorundadır. Sen re 'debug' pragma kullanarak neler olduğunu görebilirsiniz:

use re 'debug'; 
my $capture = qr/,(\d)/; 
 
Compiling REx ",(\d)" 
Final program: 
    1: EXACT (3) 
    3: OPEN1 (5) 
    5: DIGIT (6) 
    6: CLOSE1 (8) 
    8: END (0) 
anchored "," at 0 (checking anchored) minlen 2 
Freeing REx: ",(\d)" 
use re 'debug'; 
my $lookahead = qr/,(?=\d)/; 
 
Compiling REx ",(?=\d)" 
Final program: 
    1: EXACT (3) 
    3: IFMATCH[0] (8) 
    5: DIGIT (6) 
    6: SUCCEED (0) 
    7: TAIL (8) 
    8: END (0) 
anchored "," at 0 (checking anchored) minlen 1 
Freeing REx: ",(?=\d)" 

ben çoğu durumda yakalayan daha hızlı olması için yeşil ışık bakmak beklediğiniz, ancak diğer iplik de belirtildiği gibi regex performansı veriye bağlı olabilir.

+0

"Yeniden" pragma'yı düşünmeliydim. Teşekkürler! – mpe

-1

Her zaman olduğu gibi çalışır daha hızlı kodunu iki adet olduğunu bilmek istediğinizde, bunu test etmek zorunda:

#!/usr/bin/perl 

use 5.012; 
use warnings; 
use Benchmark qw<cmpthese>; 

say "Extreme ,,,:"; 
my $Text = ',' x (my $LEN = 512); 
cmpthese my $TIME = -10, my $CMP = { 
    capture => \&capture, 
    lookahead => \&lookahead, 
}; 

say "\nExtreme ,0,0,0:"; 
$Text = ',0' x $LEN; 
cmpthese $TIME, $CMP; 

my $P = 0.01; 
say "\nMixed (@{[$P * 100]}% zeros):"; 
my $zeros = $LEN * $P; 
$Text = ',' x ($LEN - $zeros) . ',0' x $zeros; 
cmpthese $TIME, $CMP; 

sub capture { 
    local $_ = $Text; 
    s/,(\d)/$1/; 
} 

sub lookahead { 
    local $_ = $Text; 
    s/,(?=\d)//; 
} 

kriter üç farklı durumlarda test eder: Sadece

  1. ', '
  2. sadece
  3. ', 0'
  4. % 1 '0' , kalan','
Benim makinede ve benim perl sürümü ile

, bu sonuçlar üretir:

Extreme ,,,: 
      Rate capture lookahead 
capture 23157/s  --  -1% 
lookahead 23362/s  1%  -- 

Extreme ,0,0,0: 
       Rate capture lookahead 
capture 419476/s  --  -65% 
lookahead 1200465/s  186%  -- 

Mixed (1% zeros): 
      Rate capture lookahead 
capture 22013/s  --  -4% 
lookahead 22919/s  4%  -- 

Bu sonuçlar ileriye bakma sürümü neredeyse sadece virgül durumunda hariç, yakalama çok daha hızlı olduğu varsayımını kanıtlar. Ve PSIAlt'ın kendi yorumunda zaten açıkladığı gibi, gerçekten de şaşırtıcı değil. İki regexes bazı kıyaslama testlerini yapmak

Saygılarımızla, Matthias

+1

Soru, _which_ daha hızlı değil, ancak _why_. –

+0

Bunu nasıl test edeceğimi biliyorum ve aslında kendim yaptım. Gösterdiğiniz için teşekkürler; Sonuçlarınız çok açıklayıcı! – mpe

İlgili konular