$30 off During Our Annual Pro Sale. View Details »

Swiftで実装するHTML特殊文字の高速処理

sonson
September 18, 2017

 Swiftで実装するHTML特殊文字の高速処理

iOSDC2017での発表スライドです.

sonson

September 18, 2017
Tweet

More Decks by sonson

Other Decks in Programming

Transcript

  1. How to accelerate string processor in Swift.
    Tech.
    Yuichi Yoshida
    Researcher, DENSO IT Laboratory, Inc.
    #iOSDC2017
    @sonson_twit
    © 2014 DENSO IT Laboratory, Inc., All rights reserved. Redistribution or public display not permitted without written permission from DENSO IT Laboratory, Inc.
    SwiftͰ࣮૷͢ΔHTMLಛघจࣈͷߴ଎ॲཧ

    View Slide

  2. ࣗݾ঺հ
    • sonson
    • twitter: sonson_twit
    • github: sonsongithub
    • portfolioʢ࠷ۙͷʣ
    • reddift(SwiftͰॻ͍ͨreddit.comͷAPIϥούʔ)
    • numsw(Swift PlaygroundsͰಈ͘ػցֶश༻notebook)
    • HTMLSpecialCharacters(ࠓ೔ͷ͓࿩)
    • ࢓ࣄ
    • ը૾ೝࣝɾݕࡧɾػցֶशͷݚڀ΍։ൃ

    View Slide

  3. View Slide

  4. View Slide

  5. ໨త
    • 2tch
    • SwiftͰॻ͖͍ͨ
    • ࠷େ1000ߦͷςΩετΛॲཧ͢Δ
    • ΍Δ͜ͱ
    • ཁૉͷ੾Γग़͠ɾɾɾσϦϛλ<>, վߦίʔυ
    • HTMLಛघจࣈUnescape
    • ຊจͷύʔεɼϨΠΞ΢τ
    • 1000ݸ͋Δͱɼ1[msec/item]Ͱ΋1ඵ͔͔Δ
    • 30[msec]Ͱ1000ݸॲཧͰ͖Δͷ͕໨ඪ
    • ආ͚ΒΕͳ͍ਖ਼نදݱॲཧ͕஗͍

    View Slide

  6. HTMLಛघจࣈ
    • W3CͰఆٛ͞Ε͍ͯΔ
    • &<>ͳͲͷςΩετʹͦͷ··ॻ͚ͳ͍ಛघͳจࣈ
    • Escape/Unescapeʔ& & &
    • ໊લ
    • 10ਐ਺͋Δ͍͸16ਐ਺ͷจࣈίʔυ
    & &
    escape
    & &
    unescape

    View Slide

  7. ՝୊
    • Google Toolbox
    • SwiftʹҠ২΋؆୯
    • ଎౓͸΄ͱΜͲมΘΒͳ͍
    • ͔͔ͤͬͩ͘Β଎͍ͨ͘͠
    • StringܕͰॲཧ͍ͯ͠ΔݶΓଟ෼͔ΘΒͳ͍
    • Stringܕ͸ಉ͡จࣈΛ୳͢ίετ΋େ͖͍
    • decode͢ΔલͷੜσʔλͰॲཧ͢Ε͹଎͘ͳΔʂ

    View Slide

  8. String͚ͩͰ΍Δطଘख๏
    J T B N Q B
    J T B
    จࣈྻ
    จࣈྻ

    จࣈྻ
    Ұக֬ೝ

    จࣈྻ
    Ұக֬ೝ
    B N Q
    จࣈྻ
    B N Q
    E F H
    O P U
    ௕͕͞ࡾจࣈͷ
    ࣙॻ(จࣈྻ)
    ɾɾɾɾ
    ࣙॻ୳ࡧ
    ஔ׵
    J T B N Q B
    จࣈྻ

    View Slide

  9. ੜσʔλ΍Δύλʔϯ
    Y Y Y Y Y YE Y YC Y Y
    Y Y Y Y Y Y
    [Unichar]
    [Unichar]
    Y YE Y
    [Unichar] ࣙॻ୳ࡧ
    ஔ׵
    J T B N Q B
    จࣈྻ
    Y Y Y Y Y YE Y YC Y Y
    [Unichar]
    Y YE Y
    Y Y Y
    Y YE Y
    ௕͕͞ࡾจࣈͷ
    ࣙॻ(จࣈྻ)
    ɾɾɾ
    J T B
    จࣈྻ
    encode
    decode
    Y
    ୳͢
    YC
    ୳͢
    Unichar Unichar

    View Slide

  10. ଎౓ൺֱ(iPhone7)
    FTDBQF

    ճ
    VOFTDBQF
    ճ
    ߦ෼ׂ

    ߦ
    )5.-λάআڈ
    :BIPPͷτοϓ
    1SPQPTFE Y
    Y
    Y
    Y

    จࣈྻͷ··
    ॲཧ





    ※୯Ґ͸[msec]
    ※unescapeͷׅހ಺ͷ਺஋͸NSAttributedStringΛ࢖ͬͨࢀߟ஋

    View Slide

  11. ίʔυ্ͷ՝୊Λߟ͑Α͏

    View Slide

  12. StringΛutf16ͷunicharͷ഑ྻʹ͢Δ
    public var unescapeHTML: String {
    var buffer = [unichar](repeating: 0, count: utf16.count)
    NSString(string: self).getCharacters(&buffer)
    var end = buffer.endIndex
    let ampersand = unichar(UInt8(ascii: "&"))
    let semicolon = unichar(UInt8(ascii: ";"))
    let sharp = unichar(UInt8(ascii: "#"))
    let hexPrefixes = ["X", "x"].map { unichar(UInt8(ascii: $0)) }
    ΋͸΍จࣈͰ͸ͳ͍ͷͰɼ”&”ͳͲͷจࣈίʔυσʔλ
    Λ͋Β͔͡Ί࡞੒͓ͯ͘͠

    View Slide

  13. όοϑΝͷಈ͖
    Y Y Y Y Y YE Y YC Y Y Y Y Y Y YE Y YC Y Y
    &ͷ୳ࡧ
    Y Y Y Y Y YE Y YC Y Y Y Y Y Y YE Y YC Y Y
    ;ͷ୳ࡧ
    Y Y Y Y Y YE Y YC Y Y Y Y Y Y Y
    ஔ׵
    Y Y Y Y Y YE Y YC Y Y Y Y Y Y Y
    ࣍ͷ&ͷ୳ࡧ

    View Slide

  14. ඞཁʹͳͬͯ͘Δॲཧ
    • Ϛονϯά
    • ಡΈऔͬͨescapeจࣈྻͱςʔϒϧͷϚονϯά
    Y Y Y Y Y YE Y YC Y Y
    Y YE Y
    Y YE Y Y YE Y Y Y Y Y Y Y
    ɾɾɾɾ
    Table
    Ϛονϯά

    View Slide

  15. จࣈྻͷҰகΛνΣοΫ͢Δίʔυ
    if let t = getTable(length: $0.count) {
    for i in 0..var match = true
    if memcmp($0.unescapingCodes, unichars, length) == 0 {
    return t[i].code
    }
    }
    }
    throw HTMLSpecialCharactersError.invalidEscapeSquenc
    ΋ͬͱφ΢͍ײ͡Ͱ

    View Slide

  16. จࣈྻͷҰகΛνΣοΫ͢Δίʔυ
    do {
    try getTable(length: length)?.forEach({
    if memcmp($0.unescapingCodes, unichars, length) == 0 {
    throw MyError.notErrorMatchedUnicode(code: $0.code)
    }
    })
    throw MyError.invalidEscapeSquence
    } catch MyError.notErrorMatchedUnicode(let code) {
    return code
    }
    forEach͸ɼྫ֎Ͱൈ͚ΒΕΔ
    errorͷܕʹ໭Γ஋ΛຒΊࠐΜͰ͓͚͹஋Λड͚औΕΔ

    View Slide

  17. 16ਐ๏ͷจࣈྻΛUTF16ίʔυʹม׵
    B Y ' # $ B T
    Y Y Y Y Y Y Y Y Y Y Y Y Y Y
    128700 = 1 x 65536 + 15 x 4096 + 6 x 256 + 11x16 + 12
    ݩͷจࣈྻ
    unicharͷ഑ྻ
    ίʔυ

    View Slide

  18. 16ਐ਺ͷ৔߹
    // 16ਐ਺ͷจࣈྻ͔Β੔਺Λ࡞Δ
    let utf16: UInt = try utf16Storage.reduce(0) {
    switch $1 {
    case 48...57: return UInt($0) << 4 + UInt($1) - 48
    case 65...70: return UInt($0) << 4 + UInt($1) - 65 + 10
    case 97...102: return UInt($0) << 4 + UInt($1) - 97 + 10
    default: throw HTMLSpecialCharactersError.invalidHexSquence
    }
    }
    return [unichar(utf16)]
    10ਐ਺ͷ৔߹΋ಉ༷ʹ10ഒͣͭͯ͠଍ͤ͹Α͍

    View Slide

  19. ·ͱΊΔͱ
    J T B N Q B
    J T B
    Y Y Y Y Y YE Y YC Y Y
    String
    Unichar
    Y Y Y Y Y Y
    Unichar
    String
    encode
    matching&replace
    decode
    ಉ͡όοϑΝ

    View Slide

  20. ͜ΕͩͱΫϥογϡ͠·͢

    View Slide

  21. ·ʔͪΌΜ͕Ϟʔχϯά່ɻϦʔμʔʹͳΔ·Ͱݟಧ͚ΔεϨ
    Part76ʲʳ [ແஅసࡌېࢭ]©2ch.net
    ʂ

    View Slide

  22. Y Y Y Y Y Y Y Y Y Y Y Y Y Y
    Y Y Y%&" Y%% Y Y Y
    ֆจࣈʙ佛ʢ΄͚ͬʣ໰୊
    B Y ' " B T
    1F60AΛαϩήʔτϖΞʹ෼ղ
    Y%&" Y%%
    ※Unichar͸16bit
    B B T
    String
    [Unichar]
    [Unichar]
    [Unichar]
    String
    decode

    View Slide

  23. UTF16ͷ஋͔ΒunicharೋͭΛ࡞Δ
    V V V V V Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
    UTF16ͷ஋ͷϏοτίʔυ
    X X X X Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
    unichar Ұͭ໨ unichar ೋͭ໨
    X X X X V V V V V
    = - 1

    View Slide

  24. ίʔυͰॻ͘ͱ
    let w: UInt
    = (scalar & 0b00000000000111110000000000000000) >> 16 - 1
    let x1: UInt
    = (scalar & 0b00000000000000001111110000000000) >> 10
    let x2: UInt
    = (scalar & 0b00000000000000000000001111111111) >> 0
    let u1: UInt16
    = UInt16((0b11011000 << 8) + (w << 6) + x1)
    let u2: UInt16
    = UInt16(UInt(0b11011100 << 8) + x2)
    return [u1, u2]
    }

    View Slide

  25. Escape
    • Unscapeͱൺֱͯ͠ɼͪΐͬͱେม
    • ͢΂ͯͷจࣈΛݕࠪ͢Δඞཁ͕͋Δ
    • →binary treeͰݕࠪίετ௿ݮ
    • ͳΔ΂͘จࣈྻʹͤͣߴ଎Խ

    View Slide

  26. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ

    View Slide

  27. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ

    View Slide

  28. Binary search - 38Λݟ͚ͭΔ࣌

    View Slide

  29. Binary search - 38Λݟ͚ͭΔ࣌

    View Slide

  30. Binary search - 38Λݟ͚ͭΔ࣌

    View Slide

  31. Binary search - 38Λݟ͚ͭΔ࣌

    View Slide

  32. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ

    View Slide

  33. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ

    View Slide

  34. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    Y Y Y
    จࣈྻ ·ͱΊͯίϐʔ

    View Slide

  35. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ
    Y Y Y Y Y YE Y YC

    View Slide

  36. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ
    Y Y Y Y Y YE Y YC

    View Slide

  37. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ
    Y Y Y Y Y YE Y YC

    View Slide

  38. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ
    Y Y Y Y Y YE Y YC Y Y
    ·ͱΊͯίϐʔ

    View Slide

  39. Escape
    Y Y Y Y Y Y
    [Unichar]
    J T B
    จࣈྻ
    Y b
    Y
    Y A
    Y$
    Y&
    Y 
    Y 
    unescape
    ͢΂͖จࣈίʔυҰཡ
    [Unichar]
    Ξ΢τϓοτ༻ͷόοϑΝ
    binary search
    log(n)
    จࣈྻ
    Y Y Y Y Y YE Y YC Y Y
    J T B N Q B
    decode

    View Slide

  40. վߦίʔυͰ੾Γ෼͚Δͱ͖
    • จࣈྻΛ[Unichar]ͷίʔυʹม׵
    • [Unichar]͔Βɼ‘\n’ΛόοϑΝ͔Β୳͢
    • ‘\n’Ͱғ·ΕΔ[Unichar]ͷҰ෦ΛStringʹม׵
    • ޮՌ
    • ߴ଎Ͱ͢
    • ੲͷiOS2,3ͷࠒ͸NSStringͷσίʔμ͕ΰϛ
    • 1ߦͣͭόΠφϦ͔Βಡ·ͳ͍ͱσʔλ͕શ໓
    • ಛఆͷจࣈ͕͋ΔߦΛؚΉͱσίʔυʹࣦഊ
    • ෼͚Ε͹ɼಛఆͷߦ͚ͩͷࣦഊʹ੾Γ෼͚ΒΕΔ

    View Slide

  41. Pros. & cons.
    • String
    • จࣈྻͷൺֱ͸஗͍ - ஋ΛݟΔ͚ͩͳͷͰ
    • จࣈྻͷ௥Ճɼஔ׵ɼ࡟আ͸஗͍
    • rangeOfͱ͔ɼcomponentsOfͱ͔͕࢖͑Δ
    • [Unichar]
    • ഑ྻΛͦͷ··ѻ͏ͷͰɼΤϥʔॲཧͱ͔େม
    • ഑ྻͷ֬อͱ͔ίʔυ͕େม
    • ԿΛ͢Δͷ΋ίʔσΟϯά͕େม

    View Slide

  42. ଎౓ൺֱ(iPhone7)
    FTDBQF

    ճ
    VOFTDBQF
    ճ
    ߦ෼ׂ

    ߦ
    )5.-λάআڈ
    :BIPPͷτοϓ
    1SPQPTFE Y
    Y
    Y
    Y

    จࣈྻͷ··
    ॲཧ





    ※୯Ґ͸[msec]
    ※unescapeͷׅހ಺ͷ਺஋͸NSAttributedStringΛ࢖ͬͨࢀߟ஋

    View Slide

  43. ·ͱΊ
    • ୯७ͳจࣈྻॲཧͷߴ଎Խ
    • จࣈίʔυͷੜσʔλͰॲཧ͢Δ
    • forEachΛ్தͰྫ֎ʹൈ͚Δ
    • ͳΔ΂͘จࣈྻʹ͠ͳ͍
    • վߦ΍ΧϯϚ۠੾Γͷ੾Γग़͠ʹ΋༗ޮ
    • ෳࡶͳॲཧ͸ఘΊͯɼਖ਼نදݱɾɾɾɾ

    View Slide

  44. Ͱ΋࠷ۙͷσόΠε଎͍Αʂ

    View Slide