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

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ಛघจࣈͷߴ଎ॲཧ
  2. ࣗݾ঺հ • sonson • twitter: sonson_twit • github: sonsongithub •

    portfolioʢ࠷ۙͷʣ • reddift(SwiftͰॻ͍ͨreddit.comͷAPIϥούʔ) • numsw(Swift PlaygroundsͰಈ͘ػցֶश༻notebook) • HTMLSpecialCharacters(ࠓ೔ͷ͓࿩) • ࢓ࣄ • ը૾ೝࣝɾݕࡧɾػցֶशͷݚڀ΍։ൃ
  3. ໨త • 2tch • SwiftͰॻ͖͍ͨ • ࠷େ1000ߦͷςΩετΛॲཧ͢Δ • ΍Δ͜ͱ •

    ཁૉͷ੾Γग़͠ɾɾɾσϦϛλ<>, վߦίʔυ • HTMLಛघจࣈUnescape • ຊจͷύʔεɼϨΠΞ΢τ • 1000ݸ͋Δͱɼ1[msec/item]Ͱ΋1ඵ͔͔Δ • 30[msec]Ͱ1000ݸॲཧͰ͖Δͷ͕໨ඪ • ආ͚ΒΕͳ͍ਖ਼نදݱॲཧ͕஗͍
  4. ՝୊ • Google Toolbox • SwiftʹҠ২΋؆୯ • ଎౓͸΄ͱΜͲมΘΒͳ͍ • ͔͔ͤͬͩ͘Β଎͍ͨ͘͠

    • StringܕͰॲཧ͍ͯ͠ΔݶΓଟ෼͔ΘΒͳ͍ • Stringܕ͸ಉ͡จࣈΛ୳͢ίετ΋େ͖͍ • decode͢ΔલͷੜσʔλͰॲཧ͢Ε͹଎͘ͳΔʂ
  5. 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 จࣈྻ
  6. ੜσʔλ΍Δύλʔϯ 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
  7. ଎౓ൺֱ(iPhone7) FTDBQF
 ճ VOFTDBQF ճ ߦ෼ׂ
 ߦ )5.-λάআڈ :BIPPͷτοϓ 1SPQPTFE

     Y  Y  Y  Y จࣈྻͷ·· ॲཧ  
    ※୯Ґ͸[msec] ※unescapeͷׅހ಺ͷ਺஋͸NSAttributedStringΛ࢖ͬͨࢀߟ஋
  8. 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)) } ΋͸΍จࣈͰ͸ͳ͍ͷͰɼ”&”ͳͲͷจࣈίʔυσʔλ Λ͋Β͔͡Ί࡞੒͓ͯ͘͠
  9. όοϑΝͷಈ͖ 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 ࣍ͷ&ͷ୳ࡧ
  10. ඞཁʹͳͬͯ͘Δॲཧ • Ϛονϯά • ಡΈऔͬͨ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 Ϛονϯά
  11. จࣈྻͷҰகΛνΣοΫ͢Δίʔυ if let t = getTable(length: $0.count) { for i

    in 0..<t.count { var match = true if memcmp($0.unescapingCodes, unichars, length) == 0 { return t[i].code } } } throw HTMLSpecialCharactersError.invalidEscapeSquenc ΋ͬͱφ΢͍ײ͡Ͱ
  12. จࣈྻͷҰகΛνΣοΫ͢Δίʔυ 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ͷܕʹ໭Γ஋ΛຒΊࠐΜͰ͓͚͹஋Λड͚औΕΔ
  13. 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ͷ഑ྻ ίʔυ
  14. 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ഒͣͭͯ͠଍ͤ͹Α͍
  15. ·ͱΊΔͱ 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 ಉ͡όοϑΝ
  16. 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
  17. 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
  18. ίʔυͰॻ͘ͱ 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] }
  19. 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) จࣈྻ
  20. 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) จࣈྻ
  21. 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) จࣈྻ
  22. 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) จࣈྻ
  23. 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 จࣈྻ ·ͱΊͯίϐʔ
  24. 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
  25. 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
  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) จࣈྻ Y Y Y Y Y YE Y YC
  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) จࣈྻ Y Y Y Y Y YE Y YC Y Y ·ͱΊͯίϐʔ
  28. 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
  29. վߦίʔυͰ੾Γ෼͚Δͱ͖ • จࣈྻΛ[Unichar]ͷίʔυʹม׵ • [Unichar]͔Βɼ‘\n’ΛόοϑΝ͔Β୳͢ • ‘\n’Ͱғ·ΕΔ[Unichar]ͷҰ෦ΛStringʹม׵ • ޮՌ •

    ߴ଎Ͱ͢ • ੲͷiOS2,3ͷࠒ͸NSStringͷσίʔμ͕ΰϛ • 1ߦͣͭόΠφϦ͔Βಡ·ͳ͍ͱσʔλ͕શ໓ • ಛఆͷจࣈ͕͋ΔߦΛؚΉͱσίʔυʹࣦഊ • ෼͚Ε͹ɼಛఆͷߦ͚ͩͷࣦഊʹ੾Γ෼͚ΒΕΔ
  30. Pros. & cons. • String • จࣈྻͷൺֱ͸஗͍ - ஋ΛݟΔ͚ͩͳͷͰ •

    จࣈྻͷ௥Ճɼஔ׵ɼ࡟আ͸஗͍ • rangeOfͱ͔ɼcomponentsOfͱ͔͕࢖͑Δ • [Unichar] • ഑ྻΛͦͷ··ѻ͏ͷͰɼΤϥʔॲཧͱ͔େม • ഑ྻͷ֬อͱ͔ίʔυ͕େม • ԿΛ͢Δͷ΋ίʔσΟϯά͕େม
  31. ଎౓ൺֱ(iPhone7) FTDBQF
 ճ VOFTDBQF ճ ߦ෼ׂ
 ߦ )5.-λάআڈ :BIPPͷτοϓ 1SPQPTFE

     Y  Y  Y  Y จࣈྻͷ·· ॲཧ  
    ※୯Ґ͸[msec] ※unescapeͷׅހ಺ͷ਺஋͸NSAttributedStringΛ࢖ͬͨࢀߟ஋