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

[PL] (4dev, JS) Nie ma nic prostszego niż napisanie wolnego regexpa

mrzasa
April 09, 2018

[PL] (4dev, JS) Nie ma nic prostszego niż napisanie wolnego regexpa

Slajdy z prezentacji podczas 4 Developers 2018 o wydajności regexpów, odmiana JavaScript.

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

April 09, 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
    4Developers, 09.04.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. 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

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

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

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

    View Slide

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

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

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

  17. View Slide

  18. POWTÓRZENIA
    POWTÓRZENIA

    View Slide

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

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

    View Slide

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

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

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

    View Slide

  24. CATASTROPHIC
    CATASTROPHIC
    BACKTRACKING
    BACKTRACKING

    View Slide

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

    View Slide

  26. DZIAŁANIA ARYTMETYCZNE
    DZIAŁANIA ARYTMETYCZNE
    320-12=
    430-
    32+1=
    /\d+[-+]\d+=/ # v1
    /(\d+[-+])+=/ # v1.0.1
    /(\d+[-+]?)+=/ #v2
    /(\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

  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 Slide

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

  29. View Slide

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

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

    View Slide

  32. 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
    var greedy = /(-?(\d+[,.]?)+)/
    // j.w., lazy
    var lazy = /(-?((\d+?[,.])+?)/
    // j.w., z ograniczeniem backtrackingu
    var unrolled = /(-?(\d+[,.])*\d+)/

    View Slide

  33. View Slide

  34. TESTY
    TESTY
    greedy lazy unrolled
    countWhole 191 ops/sec 220 ops/sec 6,689 ops/sec
    countSplit 227 ops/sec 231 ops/sec 1,782 ops/sec
    var greedy = /(-?(\d+[,.]?)+)/
    var lazy = /(-?(\d+?[,.]?)+?)/
    var unrolled = /(-?\d+([,.]\d+)*)/
    var string = "..." // ~11000 chars
    function countWhole(string, regex) {
    // count how many times regex is matched on a string
    }
    function countSplit(string, regex) {
    // split string to words,
    // then check which word is a number
    }

    View Slide

  35. REDOS - CZYLI CO MOŻE
    REDOS - CZYLI CO MOŻE
    PÓJŚĆ NIE TAK?
    PÓJŚĆ NIE TAK?

    View Slide

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

    View Slide

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

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

    View Slide

  39. View Slide

  40. View Slide

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

  42. WNIOSKI
    WNIOSKI
    optymalizacja regexpów: minimalizacja ilości kroków i
    powrotów
    główne problemy: nachodzące się zakresy lub alternatywy,
    zagnieżdżone powtórzenia
    testy: poprawny, niepoprawny, prawie poprawny napis,
    różne konfiguracje
    każdy silnik jest inny - testuj wydajność na swoim

    View Slide

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

    View Slide

  44. View Slide

  45. View Slide