Wiki spuštěna 24. 7. 2025

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

80_simplify-tags.fl
%{
 
#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
  unsigned char slovo[1500];
 
%}
 
%%
\<MMt[^\>]*\>.{14}8 {
  strcpy(slovo,yytext);
  slovo[yyleng-13]=0;
  fprintf(yyout,"%s------------8",slovo);
}
\<MMt[^\>]*\>P7-.[34]--- {
  strcpy(slovo,yytext);
  slovo[yyleng-5]='-';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>P6-.[23467] {
  strcpy(slovo,yytext);
  slovo[yyleng-2]='-';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>P[1S]...[XZMIN][SP]3 {
  strcpy(slovo,yytext);
  slovo[yyleng-3]='-';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>P[1S]...FP3 {
  strcpy(slovo,yytext);
  slovo[yyleng-3]='-';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>Vs......[FPRX] {
  strcpy(slovo,yytext);
  slovo[yyleng-1]='-';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>Vc.X...3 {
  strcpy(slovo,yytext);
  slovo[yyleng-1]='-';
  slovo[yyleng-5]='-';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>C\} {
  strcpy(slovo,yytext);
  slovo[yyleng-1]='=';
  fprintf(yyout,"%s",slovo);
}
\<MMt[^\>]*\>VB-X---X....... {
  strcpy(slovo,yytext);
  slovo[yyleng-15]=0;
  fprintf(yyout,"%sXX-------------",slovo);
}
\>[\-\+]?[0-9][^\<]*\<MMl[^\>]*\>[^\<]+\<MMt[^\>]*\>C[nlr].{13} {
  strcpy(slovo,yytext);
  slovo[yyleng-14]=0;
  fprintf(yyout,"%s=-------------",slovo);
}
\<MMl[^\>]*\>co\<MMt[^\>]*\>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

80_simplify-tags.pl
#!/usr/bin/perl
 
# use re 'debugcolor';
# use open ':utf8';
# use utf8;
 
# binmode( STDIN,  ':utf8' );
# binmode( STDOUT, ':utf8' );
# binmode( STDERR, ':utf8' );
 
while ($radek = <STDIN>) {
    $radek =~ s/(<MMt[^>]*>)P7-.([34]---)/$1P7--$2/g;
    $radek =~ s/(<MMt[^>]*>)P6-.([23467])/$1P6--$2/g;
    $radek =~ s/(<MMt[^>]*>Vs......)[FPRX]/$1-/g;
    $radek =~ s/(<MMt[^>]*>Vc.)X(...)3/$1-$2-/g;
    if ($radek =~ /<MMl[^>]*>co</) {
	$radek =~ s/(<MMt[^>]*>P4).../$1---/g;
    }
    $radek =~ s/(>([\-\+])?[0-9][^<]*<MMl[^>]*>[^<]+<MMt[^>]*>)C[nlr]............./$1C=-------------/;
    $radek =~ s/(<MMt[^>]*>)C}/$1C=/g;
    $radek =~ s/(<MMt[^>]*>P[1S]...)[XZMIN]([SP]3)/$1-$2/g;
    $radek =~ s/(<MMt[^>]*>P[1S]...)F(P3)/$1-$2/g;
    $radek =~ s/(<MMt[^>]*>)VB-X---X......./$1XX-------------/g;
    $radek =~ s/(<MMt[^>]*>..)............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

80_simplify-tags-faster.pl
#!/usr/bin/perl
 
# use re 'debugcolor';
# use open ':utf8';
# use utf8;
 
# binmode( STDIN,  ':utf8' );
# binmode( STDOUT, ':utf8' );
# binmode( STDERR, ':utf8' );
 
while ($radek = <STDIN>) {
    if ($radek =~ /<MMt[^>]*>.{14}8/) {
	$radek =~ s/(<MMt[^>]*>..).{12}8/$1------------8/;
    }
    if ($radek =~ /<MMt[^>]*>P[67]/) {
	$radek =~ s/(<MMt[^>]*>)P7-.([34]---)/$1P7--$2/g;
	$radek =~ s/(<MMt[^>]*>)P6-.([23467])/$1P6--$2/g;
    }
    elsif ($radek =~ /<MMt[^>]*>P[1S]/) {
	$radek =~ s/(<MMt[^>]*>P[1S]...)[XZMIN]([SP]3)/$1-$2/g;
	$radek =~ s/(<MMt[^>]*>P[1S]...)F(P3)/$1-$2/g;
    }
    elsif ($radek =~ /<MMt[^>]*>Vs/) {
	$radek =~ s/(<MMt[^>]*>Vs......)[FPRX]/$1-/g;
    }
    elsif ($radek =~ /<MMt[^>]*>Vc/) {
	$radek =~ s/(<MMt[^>]*>Vc.)X(...)3/$1-$2-/g;
    }
    elsif ($radek =~ /<MMt[^>]*>C[nlr]/) {
	$radek =~ s/(>([\-\+])?[0-9][^<]*<MMl[^>]*>[^<]+<MMt[^>]*>)C[nlr]............./$1C=-------------/;
    }
    elsif ($radek =~ /<MMt[^>]*>C}/) {
	$radek =~ s/(<MMt[^>]*>)C}/$1C=/;
    }
    elsif ($radek =~ /<MMt[^>]*>VB-X/) {
	$radek =~ s/(<MMt[^>]*>)VB-X---X......./$1XX-------------/g;
    }
    elsif ($radek =~ /<MMl[^>]*>co</) {
	$radek =~ s/(<MMt[^>]*>P4).../$1---/g;
    }
    print STDOUT "$radek";
}

Rust

  • První naivní pokus, žádná sláva
  • - Nepřehledné
  • - Pomalé

Zdrojový kód

main.rs
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<f><MMt[^>]*>..).{12}8").unwrap();
        static ref P7_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>P7-).(?P<s>[34]---)").unwrap();
        static ref P6_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>P6-).(?P<s>[23467])").unwrap();
        static ref P1SX_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>P[1S]...)[XZMIN](?P<s>[SP]3)")
            .unwrap();
        static ref P1SF_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>P[1S]...)F(?P<s>P3)").unwrap();
        static ref VS_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>Vs......)[FPRX]").unwrap();
        static ref VC_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>Vc.)X(?P<s>...)3").unwrap();
        static ref CNLR_REGEX:
        Regex = Regex::new(r"(?P<f>>([\-\+])?[0-9][^<]*<MMl[^>]*>[^<]+<MMt[^>]*>C)[nlr](?P<s>.{13})")
            .unwrap();
        static ref CROM_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>C)\}").unwrap();
        static ref VBX_REGEX:
        Regex = Regex::new(r"(?P<f><MMt[^>]*>)VB-X---X.{7}").unwrap();
        static ref CO_REGEX:
        Regex = Regex::new(r"(?P<f><MMl[^>]*>co<MMt[^>]*>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 %

QR Code
QR Code wiki:user:skoumal:benchmark (generated for current page)