====== Rychlost regexu v různých jazycích ====== * Pomocné skripty přispívají k době zpracování korpusů * Testované jazyky: * ''flex'' * Perl * Optimalizovaný Perl (pečlivě promyšlené pořadí příkazů, testy, na které řádky se má regex pustit atd.) * Rust * Testovaný skript: ''80_simpify_tags'' * Testovaný text: SYN2015 po vidu (''/store/corp/SYN2015-RC3/csts-rules-frazrl-rules1-rulh1-tag-vid'', 121.277.800 pozic) * Stroj: ''grimm'' (Supermicro) ===== flex ===== * + Zkompilovaný jako C, velmi rychlý * - Nezvládá utf-8 * - Nepřehledný ==== Zdrojový kód ==== %{ #include #include #include unsigned char slovo[1500]; %} %% \]*\>.{14}8 { strcpy(slovo,yytext); slovo[yyleng-13]=0; fprintf(yyout,"%s------------8",slovo); } \]*\>P7-.[34]--- { strcpy(slovo,yytext); slovo[yyleng-5]='-'; fprintf(yyout,"%s",slovo); } \]*\>P6-.[23467] { strcpy(slovo,yytext); slovo[yyleng-2]='-'; fprintf(yyout,"%s",slovo); } \]*\>P[1S]...[XZMIN][SP]3 { strcpy(slovo,yytext); slovo[yyleng-3]='-'; fprintf(yyout,"%s",slovo); } \]*\>P[1S]...FP3 { strcpy(slovo,yytext); slovo[yyleng-3]='-'; fprintf(yyout,"%s",slovo); } \]*\>Vs......[FPRX] { strcpy(slovo,yytext); slovo[yyleng-1]='-'; fprintf(yyout,"%s",slovo); } \]*\>Vc.X...3 { strcpy(slovo,yytext); slovo[yyleng-1]='-'; slovo[yyleng-5]='-'; fprintf(yyout,"%s",slovo); } \]*\>C\} { strcpy(slovo,yytext); slovo[yyleng-1]='='; fprintf(yyout,"%s",slovo); } \]*\>VB-X---X....... { strcpy(slovo,yytext); slovo[yyleng-15]=0; fprintf(yyout,"%sXX-------------",slovo); } \>[\-\+]?[0-9][^\<]*\]*\>[^\<]+\]*\>C[nlr].{13} { strcpy(slovo,yytext); slovo[yyleng-14]=0; fprintf(yyout,"%s=-------------",slovo); } \]*\>co\]*\>P4... { strcpy(slovo,yytext); slovo[yyleng-3]=0; fprintf(yyout,"%s---",slovo); } . ECHO; \n ECHO; %% main() { yylex(); } ===== Perl ===== * + Přehledný regex * - Nekompilovaný, pomalejší než C ==== Zdrojový kód ==== #!/usr/bin/perl # use re 'debugcolor'; # use open ':utf8'; # use utf8; # binmode( STDIN, ':utf8' ); # binmode( STDOUT, ':utf8' ); # binmode( STDERR, ':utf8' ); while ($radek = ) { $radek =~ s/(]*>)P7-.([34]---)/$1P7--$2/g; $radek =~ s/(]*>)P6-.([23467])/$1P6--$2/g; $radek =~ s/(]*>Vs......)[FPRX]/$1-/g; $radek =~ s/(]*>Vc.)X(...)3/$1-$2-/g; if ($radek =~ /]*>co]*>P4).../$1---/g; } $radek =~ s/(>([\-\+])?[0-9][^<]*]*>[^<]+]*>)C[nlr]............./$1C=-------------/; $radek =~ s/(]*>)C}/$1C=/g; $radek =~ s/(]*>P[1S]...)[XZMIN]([SP]3)/$1-$2/g; $radek =~ s/(]*>P[1S]...)F(P3)/$1-$2/g; $radek =~ s/(]*>)VB-X---X......./$1XX-------------/g; $radek =~ s/(]*>..)............8/$1------------8/g; # odkomentováno 27.7.2016: zkratky bez dalšího určení print STDOUT "$radek"; } ===== Optimalizovaný Perl ===== * Regexy uspořádány do ''if - else'' bloků * Testuje se, zda se má vůbec regex použít * + Rychlejší než předchozí Perl * - Trochu méně přehledný ==== Zdrojový kód ==== #!/usr/bin/perl # use re 'debugcolor'; # use open ':utf8'; # use utf8; # binmode( STDIN, ':utf8' ); # binmode( STDOUT, ':utf8' ); # binmode( STDERR, ':utf8' ); while ($radek = ) { if ($radek =~ /]*>.{14}8/) { $radek =~ s/(]*>..).{12}8/$1------------8/; } if ($radek =~ /]*>P[67]/) { $radek =~ s/(]*>)P7-.([34]---)/$1P7--$2/g; $radek =~ s/(]*>)P6-.([23467])/$1P6--$2/g; } elsif ($radek =~ /]*>P[1S]/) { $radek =~ s/(]*>P[1S]...)[XZMIN]([SP]3)/$1-$2/g; $radek =~ s/(]*>P[1S]...)F(P3)/$1-$2/g; } elsif ($radek =~ /]*>Vs/) { $radek =~ s/(]*>Vs......)[FPRX]/$1-/g; } elsif ($radek =~ /]*>Vc/) { $radek =~ s/(]*>Vc.)X(...)3/$1-$2-/g; } elsif ($radek =~ /]*>C[nlr]/) { $radek =~ s/(>([\-\+])?[0-9][^<]*]*>[^<]+]*>)C[nlr]............./$1C=-------------/; } elsif ($radek =~ /]*>C}/) { $radek =~ s/(]*>)C}/$1C=/; } elsif ($radek =~ /]*>VB-X/) { $radek =~ s/(]*>)VB-X---X......./$1XX-------------/g; } elsif ($radek =~ /]*>co]*>P4).../$1---/g; } print STDOUT "$radek"; } ===== Rust ===== * První naivní pokus, žádná sláva * - Nepřehledné * - Pomalé ==== Zdrojový kód ==== extern crate lazy_static; extern crate regex; use std::io; use regex::Regex; use lazy_static::*; fn main() { loop { let mut radek = String::new(); match io::stdin().read_line(&mut radek) { Ok(0) => break, Ok(_) => make_replacement(radek), Err(e) => panic!(e) } // radek.clear(); } } fn make_replacement(mut radek: String) { lazy_static! { static ref ABBR_REGEX: Regex = Regex::new(r"(?P]*>..).{12}8").unwrap(); static ref P7_REGEX: Regex = Regex::new(r"(?P]*>P7-).(?P[34]---)").unwrap(); static ref P6_REGEX: Regex = Regex::new(r"(?P]*>P6-).(?P[23467])").unwrap(); static ref P1SX_REGEX: Regex = Regex::new(r"(?P]*>P[1S]...)[XZMIN](?P[SP]3)") .unwrap(); static ref P1SF_REGEX: Regex = Regex::new(r"(?P]*>P[1S]...)F(?PP3)").unwrap(); static ref VS_REGEX: Regex = Regex::new(r"(?P]*>Vs......)[FPRX]").unwrap(); static ref VC_REGEX: Regex = Regex::new(r"(?P]*>Vc.)X(?P...)3").unwrap(); static ref CNLR_REGEX: Regex = Regex::new(r"(?P>([\-\+])?[0-9][^<]*]*>[^<]+]*>C)[nlr](?P.{13})") .unwrap(); static ref CROM_REGEX: Regex = Regex::new(r"(?P]*>C)\}").unwrap(); static ref VBX_REGEX: Regex = Regex::new(r"(?P]*>)VB-X---X.{7}").unwrap(); static ref CO_REGEX: Regex = Regex::new(r"(?P]*>co]*>P4)...").unwrap(); } let mut after = ABBR_REGEX.replace_all(&radek, "$f------------8") .to_string(); radek = after; after = P7_REGEX.replace_all(&radek, "$f-$s").to_string(); radek = after; after = P6_REGEX.replace_all(&radek, "$f-$s").to_string(); radek = after; after = P1SX_REGEX.replace_all(&radek, "$f-$s").to_string(); radek = after; after = P1SF_REGEX.replace_all(&radek, "$f-$s").to_string(); radek = after; after = VS_REGEX.replace_all(&radek, "$f-").to_string(); radek = after; after = VC_REGEX.replace_all(&radek, "$f-$s-").to_string(); radek = after; after = CNLR_REGEX.replace_all(&radek, "$f=-------------").to_string(); radek = after; after = CROM_REGEX.replace_all(&radek, "$f=").to_string(); radek = after; after = VBX_REGEX.replace_all(&radek, "$fXX-------------").to_string(); radek = after; after = CO_REGEX.replace_all(&radek, "$f---").to_string(); radek = after; after = P1SF_REGEX.replace_all(&radek, "$f-$s").to_string(); radek = after; print!("{}",radek); } ===== Porovnání ===== ^ Porovnání jazyků ^^^^^ | | 1byte || utf8 || ^ flex | 3m58.761s | 100 % | NA || ^ Perl | 6m36.372s | 166 % | 14m29.309s | 364 % | ^ Opt. Perl | 4m50.576s | 122 % | 9m47.725s | 246 %| ^ Rust | NA || 9m07.683s | 229 % |