2012-12-03 17 views
7

Câu hỏi này được lấy cảm hứng từ this other one.Tại sao là lookahead (đôi khi) nhanh hơn so với chụp?

So sánh s/,(\d)/$1/ đến s/,(?=\d)//: trước đây sử dụng nhóm chụp để chỉ thay thế chữ số chứ không phải dấu phẩy, dấu hai chấm sử dụng dấu kiểm để xác định dấu phẩy có thành công hay không. Tại sao sau này đôi khi nhanh hơn, như được thảo luận trong this answer?

+1

Làm một số xét nghiệm chuẩn trên hai regexes tôi có thể không thực sự xác định bất kỳ sự khác biệt tuyệt vời. Cả hai đều rất nhanh. Lưu ý rằng áp dụng cho các regex này, không bắt được so với lookahead. – TLP

+4

Rõ ràng: nắm bắt lực lượng nhóm để sao chép dữ liệu và sau đó thay thế nhu cầu nội suy của '$ 1', trong khi regex thứ hai chỉ là tìm/kiểm tra/loại bỏ. Tuy nhiên, sự khác biệt về tốc độ phải là vô hình. – PSIAlt

Trả lời

4

Hai phương pháp tiếp cận làm những việc khác nhau và có các loại chi phí trên cao khác nhau. Khi bạn chụp, perl phải tạo một bản sao của văn bản đã chụp. Các trận đấu nhìn về phía trước mà không cần tiêu thụ; nó phải đánh dấu vị trí nơi nó bắt đầu. Bạn có thể xem những gì đang xảy ra bằng cách sử dụng các re 'debug' pragma:

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)" 

tôi mong đợi trông-trước để được nhanh hơn so với chụp trong hầu hết các trường hợp, nhưng như đã nêu trong các chủ đề khác hiệu suất regex có thể phụ thuộc vào dữ liệu.

+0

Tôi nên nghĩ đến chữ "re' pragma". Cảm ơn! – mpe

-1

Như mọi khi, khi bạn muốn biết về hai đoạn mã hoạt động nhanh hơn, bạn phải kiểm tra nó:

#!/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)//; 
} 

Các benchmark kiểm tra ba trường hợp khác nhau:

  1. Chỉ', '
  2. Chỉ', 0'
  3. 1% '0' , phần còn lại','

Trên máy tính của tôi và với phiên bản perl của tôi, nó tạo ra những kết quả này:

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%  -- 

Những kết quả substantiates giả định rằng phiên bản nhìn về phía trước là nhanh hơn đáng kể so với chụp, trừ trường hợp của hầu hết chỉ bằng dấu phẩy. Và nó thực sự không phải là rất đáng ngạc nhiên như PSIAlt đã giải thích trong bình luận của mình.

regards, Matthias

+1

Câu hỏi không phải là _which_ nhanh hơn, nhưng _why_. –

+0

Tôi biết làm thế nào để kiểm tra điều này và trên thực tế, đã làm như vậy bản thân mình. Cảm ơn bạn đã chứng minh, mặc dù; kết quả của bạn rất minh họa! – mpe