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 Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. 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 Slide

  6. 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 Slide

  7. 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 Slide

  8. 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 Slide

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

    View Slide

  10. 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 Slide

  11. 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 Slide

  12. ...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 Slide

  13. 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 Slide

  14. 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 Slide

  15. 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 Slide

  16. 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 Slide

  17. View Slide

  18. 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 Slide

  19. ANALIZA WYDAJNOŚCI
    ANALIZA WYDAJNOŚCI

    View Slide

  20. 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 Slide

  21. WARTO BYĆ LENIWYM?
    WARTO BYĆ LENIWYM?
    " regexp text "
    /]*>/ //

    View Slide

  22. 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 Slide

  23. 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 Slide

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

    View Slide

  25. CATASTROPHIC
    CATASTROPHIC
    BACKTRACKING
    BACKTRACKING

    View Slide

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

    View Slide

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

    View Slide

  28. View Slide

  29. View Slide

  30. View Slide

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

    View Slide

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

    View Slide

  33. 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 Slide

  34. 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 Slide

  35. 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 Slide

  36. View Slide

  37. 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 Slide

  38. 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 Slide

  39. 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 Slide

  40. View Slide

  41. 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 Slide

  42. 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 Slide

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

    View Slide

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

    View Slide

  45. 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
    #
    GET /wp-login.php HTTP/1.1 69
    GET /show.aspx HTTP/1.1 15
    klient Discourse, opisane przez Sama Saffrona

    View Slide

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

    View Slide

  47. View Slide

  48. View Slide

  49. 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 Slide

  50. 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 Slide

  51. 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 Slide

  52. View Slide

  53. View Slide