Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[PL] (HackYeah) Nie ma nic prostszego niż napisanie wolnego regexpa

mrzasa
November 24, 2018

[PL] (HackYeah) Nie ma nic prostszego niż napisanie wolnego regexpa

Slajdy z prezentacji podczas hackatonu HackYeah, Warszawa 24-25.11.2018.

W prezentacji: o tym, jak działają silniki regexpów, jak to wpływa na czas działania regexpa. Oraz o tym, co złego może się stać, jeśli nie dbamy o wydajność regexpów.

mrzasa

November 24, 2018
Tweet

More Decks by mrzasa

Other Decks in Programming

Transcript

  1. NIE MA NIC PROSTSZEGO NIŻ
    NIE MA NIC PROSTSZEGO NIŻ
    NAPISANIE WOLNEGO
    NAPISANIE WOLNEGO
    REGEXPA
    REGEXPA
    MACIEK RZĄSA
    MACIEK RZĄSA
    HackYeah, 24.11.2018
    @mjrzasa

    View full-size slide

  2. I'm definitely guilty of this. When I throw a regex
    together, I never worry about performance;
    I know the target strings will generally be
    far too small to ever cause a problem.
    Jeff Atwood, 2006

    View full-size slide

  3. JEŚLI JEFF ATWOOD NIE DBA
    JEŚLI JEFF ATWOOD NIE DBA
    OD WYDAJNOŚĆ REGEXPÓW,
    OD WYDAJNOŚĆ REGEXPÓW,
    DLACZEGO JA POWINIENEM?
    DLACZEGO JA POWINIENEM?

    https://regex-performance.github.io/input.html

    View full-size slide

  4. CO DALEJ?
    CO DALEJ?
    jak właściwie działają regexpy?
    wydajność podstawowych
    elementów
    zastosowania
    co może pójść nie tak?
    czy istnieją szybkie regexpy?

    View full-size slide

  5. RUBY DEVELOPER
    RUBY DEVELOPER
    @ TEXTMASTER
    @ TEXTMASTER
    w pracy:
    Ruby, mongodb, elastic search
    automatyczne przygotowanie tekstu do
    tłumaczeń
    DDD, software that matters, agile
    dzielenie się wiedzą:
    Rzeszów Ruby User Group ( )
    Politechnika Rzeszowska
    rrug.pl

    View full-size slide

  6. JAK WŁAŚCIWIE
    JAK WŁAŚCIWIE
    DZIAŁAJĄ
    DZIAŁAJĄ
    REGEXPY?
    REGEXPY?

    View full-size slide

  7. RUBY
    RUBY
    JAVA
    JAVA
    JAVASCRIPT
    JAVASCRIPT
    pattern = /<.*>/
    pattern.match("text
    ")
    Pattern p = Pattern.compile("<.*>");
    Matcher m = p.matcher("text
    ");
    boolean b = m.matches();
    var pattern = /<.*>/;
    var results = re.exec("text
    ");

    View full-size slide

  8. TEORIA...
    TEORIA...
    gramatyka regularna
    wyrażenie regularne: abab|abbb
    automat skończony
    a b a
    a
    b
    b b b
    źródło:
    A -> abB
    B -> bb
    B -> ab
    https://swtch.com/~rsc/regexp/regexp1.html

    View full-size slide

  9. ...SPOTYKA PRAKTYKĘ
    ...SPOTYKA PRAKTYKĘ
    w teorii języków formalnych
    w silnikach wyrażeń
    regularnych
    a* a+ a|b a? a(a|b)
    a* a+ a|b a? a(a|b) a*? \d
    \W (/(\w+)\1/ -> papa WikiWiki
    /\(((?R)|\w+)\)/ -> (((12)))

    View full-size slide

  10. DWA RODZAJE SILNIKÓW
    DWA RODZAJE SILNIKÓW
    REGEXPÓW
    REGEXPÓW
    1. Text-directed
    Thompson 1968, 400 linii w C
    grep, awk, sed, go
    oparte na DFA
    2. Regex-directed
    Larry Wall, perl, 1987
    Perl-Compatible Regular Expressions
    (JavaScript, Ruby, .Net,...)
    oparte na NFA

    View full-size slide

  11. PRZYKŁAD
    PRZYKŁAD
    a b a
    a
    b
    b b b
    źródło ilustracji na tym i kolejnych slajdach:
    /abab|abbb/ =~ 'abbb'
    https://swtch.com/~rsc/regexp/regexp1.html

    View full-size slide

  12. Text-directed abab|abbb
    a b a
    a
    b
    b b b
    •abbb
    a b a
    a
    b
    b b b
    a•bbb
    a b a
    a
    b
    b b b
    ab•bb
    a b a
    a
    b
    b b b
    abb•b
    a b a
    a
    b
    b b b
    abbb•

    View full-size slide

  13. Regex-directed abab|abbb
    a b a
    a
    b
    b b b
    •abbb
    a b a
    a
    b
    b b b
    •abbb
    a b a
    a
    b
    b b b
    a•bbb
    a b a
    a
    b
    b b b
    ab•bb
    a b a
    a
    b
    b b b
    •abbb
    a b a
    a
    b
    b b b
    a•bbb
    a b a
    a
    b
    b b b
    ab•bb
    a b a
    a
    b
    b b b
    abb•b
    a b a
    a
    b
    b b b
    abbb•
    failure, backtracking

    View full-size slide

  14. CO JUŻ WIEMY?
    CO JUŻ WIEMY?
    regexpy - osobny język programowania
    dwa rodzaje silników (maszyn wirtualnych) - text-directed,
    regex-directed
    istotna jest ilość kroków i powrotów

    View full-size slide

  15. ANALIZA WYDAJNOŚCI
    ANALIZA WYDAJNOŚCI

    View full-size slide

  16. POWTÓRZENIA
    POWTÓRZENIA
    .* greedy (zachłanne)
    .*? lazy (leniwe)
    /<.*>/=~"
    regexp text "
    => "
    " # so far so good
    /<.*>/=~" regexp text "
    => " regexp text " #hmmm...
    /<[^>]*>/=~" regexp text "
    => "" # great!
    /<.*?>/=~" regexp text "
    => "" # great!

    View full-size slide

  17. WARTO BYĆ LENIWYM?
    WARTO BYĆ LENIWYM?
    " regexp text "
    /<[^>]*>/ /<.*?>/

    View full-size slide

  18. LICZY SIĘ KONTEKST
    LICZY SIĘ KONTEKST
    "
    some really long text"
    <.*> 27 kroków
    <.*?> 7 kroków
    <[^>]*> 4 kroki
    "some really long text

    "
    <.*> 5 kroków
    <.*?> 7 kroków
    <[^>]*> 4 kroki

    View full-size slide

  19. POWTÓRZENIA
    POWTÓRZENIA
    wydajność zależna od kontekstu
    zachłanne .* .+ - wydajność zależna od długości
    nadmiarowo znalezionego tekstu
    leniwe .*? .+? - wydajność zależna od długości
    szukanego tekstu
    testy pozytywne: szukany string w różnych miejscach
    tekstu
    testy negatywne: napis bardzo podobny do szukanego

    View full-size slide

  20. TO WSZYSTKO TO DROBIAZG
    TO WSZYSTKO TO DROBIAZG
    To nie po to Was tu trzymam

    View full-size slide

  21. CATASTROPHIC
    CATASTROPHIC
    BACKTRACKING
    BACKTRACKING

    View full-size slide

  22. POWTÓRZENIE W POWTÓRZENIU
    POWTÓRZENIE W POWTÓRZENIU
    /(a+)*b/
    aaaaaaaaaaaaaab

    View full-size slide

  23. POWTÓRZENIE W POWTÓRZENIU
    POWTÓRZENIE W POWTÓRZENIU
    /(a+)*b/
    aaaaaaaaaaaaaab
    aaaaaaaaaaaaaa

    View full-size slide

  24. 148 z 98301 kroków (0.15%)

    View full-size slide

  25. POWTÓRZENIE W POWTÓRZENIU
    POWTÓRZENIE W POWTÓRZENIU
    ...ale kto pisze takie regexy?
    /(a+)*b/
    aaaaaaaaaaaaaab
    aaaaaaaaaaaaaa

    View full-size slide

  26. DZIAŁANIA ARYTMETYCZNE
    DZIAŁANIA ARYTMETYCZNE
    320-12=
    430-
    32+1=
    /\d+[-+]\d+=/ # v1.0
    /(\d+[-+])+=/ # v2.0-rc
    /(\d+[-+]?)+=/ #v2.0
    /(\d+|[-+])+=/
    "320-12=" # 12 kroków
    "32-12+230=" # 18 kroków
    "32+12-320-2132+32123=" # 28 kroków
    "32+12-320-2132+32123" # 95 854 kroki

    View full-size slide

  27. COPY-PASTING
    COPY-PASTING
    (email validation)
    , Java Classname
    RegExLib, id=1757
    ^([a-zA-Z0-9])(([\-.]|[_]+)?
    ([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}
    (([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$
    OWASP Validation Regex Repository
    ^(([a-z])+.)+[A-Z]([a-z])+$
    'aaaaaaaaaaaaaaa'

    View full-size slide

  28. CZEGO UNIKAĆ?
    CZEGO UNIKAĆ?
    zagnieżdżone powtórzenia /(\d+)*\w/
    odległe, krzyżujące się powtórzenia
    /.*-some text-.*;/
    nachodzące się zakresy /\d+\w*/
    nachodzace się alternatywy
    /(\d+|\w+)/

    View full-size slide

  29. KOMPUTERY TERAZ SĄ TAK
    KOMPUTERY TERAZ SĄ TAK
    SZYBKIE, ŻE NAWET 100 000
    SZYBKIE, ŻE NAWET 100 000
    KROKÓW NIE MA ZNACZENIA!
    KROKÓW NIE MA ZNACZENIA!
    kilka słów o zastosowaniach

    View full-size slide

  30. ZLICZANIE LICZB W TEKŚCIE
    ZLICZANIE LICZB W TEKŚCIE
    co może być prostszego?
    # liczba
    # 1, 3243, 4323
    pattern = /\d+/
    # liczba z częścią dziesiętną i minusem
    # -1, 1, 32.32, -2.2324
    pattern = /-?(\d+(\.\d+)?/
    # liczba z częścią dziesiętną (kropka albo przecinek)
    # -23,23 4323.23
    pattern = /-?(\d+([.,]\d+)?)/

    View full-size slide

  31. ZLICZANIE LICZB W TEKŚCIE
    ZLICZANIE LICZB W TEKŚCIE
    # liczba z częścią dziesiętną i separatorami tysięcy
    # -21,321,321.1111 433.233,12
    greedy = /(-?(\d+[,.]?)+)/
    # j.w., lazy
    lazy = /(-?((\d+?[,.])+?)/
    # j.w., z ograniczeniem backtrackingu
    unrolled = /(-?(\d+[,.])*\d+)/
    # j.w., possesive
    possesive = /(-?((\d++[,.])++)/

    View full-size slide

  32. TESTY
    TESTY
    greedy lazy unrolled possessive
    Ruby 70.4 i/s 65.9 i/s 1,296.1 i/s 1,187.0 i/s
    JavaScript 191 i/s 220 i/s 6,689 i/s -
    iterations per second
    greedy = /(-?(\d+[,.]?)+)/
    lazy = /(-?(\d+?[,.]?)+?)/
    unrolled = /(-?\d+([,.]\d+)*)/
    possessive = /(-?(\d++[,.]?)++)/
    string = "..." # ~11000 chars
    def count(string, regex)
    # count how many times regex is matched on a string
    end

    View full-size slide

  33. LOG SEARCH
    LOG SEARCH
    NASA webserver, 196 MB
    199.72.81.55 - - [01/Jul/1995:00:00:01 -0400]
    "GET /history/apollo/ HTTP/1.0" 200 6245
    /.* - - \[(.*)\] "((.+) ?)*" (.*) (.*)/
    # 5m18,298s
    /.* - - \[(.*)\] "(.+) (.*) (HTTP\/.*)" (.*) (.*)/
    # 0m10,013s
    /\S* - - \[([^\]]*)\] "(\S+) (\S*) (HTTP\/\d.\d)"
    (\d+) (\d+)/
    # 0m5,897s

    View full-size slide

  34. REDOS - CZYLI CO MOŻE
    REDOS - CZYLI CO MOŻE
    PÓJŚĆ NIE TAK?
    PÓJŚĆ NIE TAK?
    Regular expression Denial of Service

    View full-size slide

  35. JAK ZAMULIĆ FRONTEND?
    JAK ZAMULIĆ FRONTEND?
    vue.js
    https://regex-performance.github.io/vue.html

    View full-size slide

  36. JAK ZAJĄĆ 100% PROCESORA?
    JAK ZAJĄĆ 100% PROCESORA?
    Witaj! → ¡Hola! → Salut !
    # Ruby
    # Źródła funkcji
    ::Typography.to_html_french
    # Wstaw cienką spację przed znaki interpunkcyjne
    text.gsub(/(\s|)+([!?;]+(\s|\z))/, ' \2\3')
    # Dane
    # <-58 spacji ->
    GET /wp-login.php HTTP/1.1 69
    GET /show.aspx HTTP/1.1 15
    klient Discourse, opisane przez Sama Saffrona

    View full-size slide

  37. POZWÓLMY UŻYTKOWNIKOM PISAĆ
    POZWÓLMY UŻYTKOWNIKOM PISAĆ
    REGEXPY
    REGEXPY
    feature request
    (<.*>\s*)*

    View full-size slide

  38. DOBRE PRAKTYKI
    DOBRE PRAKTYKI
    .* => [^X]*
    .*? => [^X]*
    (pre-d1|pre-e2|...) => pre-(d1|e2|...)
    (,|;|\.) => [,.;]
    (A*|B?)+ => A+(BA*)*
    \w+-\d+ => \w+-\d++, \w+-(?>\d+), \w+-(?
    =(\d+))\1

    View full-size slide

  39. WNIOSKI
    WNIOSKI
    wyrażenia regularne - teoria (języki formalne) i praktyka
    (języki programowania) nie zawsze idą w parze
    każdy silnik jest inny - sprawdzaj, jak działa Twój
    główne problemy: nachodzące się zakresy lub alternatywy,
    zagnieżdżone powtórzenia
    testy: poprawny, niepoprawny, prawie poprawny napis,
    różne konfiguracje

    View full-size slide

  40. MATERIAŁY
    MATERIAŁY
    Mastering Regular Expressions, 3rd Edition, Jefferey Friedl,
    2009
    i kolejne części (1-4)
    podziękowania dla kszubrycht
    http://www.rexegg.com
    https://www.regular-expressions.info
    https://regex101.com/
    Russ Cox
    aplikacja testowa - oryginał
    OWASP ReDoS
    Loggly: 5 techniquess
    Loggly: regexes bad better...
    Katafrakt: Regular expression how do they work?
    TextMaster: Performance of Regular Expression

    View full-size slide