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

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

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

Slajdy z prezentacji podczas SegFault Łódź 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

May 18, 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
    SegFault Łódź, 18.05.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, Java, 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. 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. 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
    ..ale kto pisze takie regexy?
    /(a+)*b/
    aaaaaaaaaab
    aaaaaaaaaa

    View Slide

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

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

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

    View Slide

  30. View Slide

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

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

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

  34. View Slide

  35. TESTY
    TESTY
    greedy = /(-?(\d+[,.]?)+)/
    lazy = /(-?(\d+?[,.]?)+?)/
    unrolled = /(-?\d+([,.]\d+)*)/
    possessive = /(-?(\d++[,.]?)++)/
    string = "..." # ~11000 chars
    def count_whole(string, regex)
    # count how many times regex is matched on a string
    end
    def count_split(string, regex) {
    # split string to words,
    # then check which word is a number
    end

    View Slide

  36. ZLICZANIE LICZB W TEKŚCIE
    ZLICZANIE LICZB W TEKŚCIE
    greedy lazy unrolled possessive
    Ruby
    count_whole 60.9 i/s 60.9 i/s 1,247.9 i/s 1,236.4 i/s
    count_split 25.0 i/s 24.5 i/s 33.1 i/s 37.7 i/s
    JavaScript
    count_whole 191 i/s 220 i/s 6,689 i/s -
    count_split 227 i/s 231 i/s 1,782 i/s -

    View Slide

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

  38. JAK ZAMULIĆ FRONTEND?
    JAK ZAMULIĆ FRONTEND?
    vue.js

    View Slide

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

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

    View Slide

  41. View Slide

  42. View Slide

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

    View Slide

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

  45. POSTMODERNIZM(!)
    POSTMODERNIZM(!)
    (...) key parts of the Computer Science grand
    narrative are the twin goals of correctness and
    then efficiency (...) the aim of developing only
    “good enough software” — software that is
    neither correct nor efficient — but is good
    enough for its context of use, is also a
    postmodern approach.
    Noble, Biddle. Postmodern Prospects for Conceptual
    Modelling. 2006

    View Slide

  46. 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?

    View Slide

  47. View Slide

  48. View Slide