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

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

F9feb45c0a049cccc3e2563f1fe2f869?s=47 sonson
September 18, 2017

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

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

F9feb45c0a049cccc3e2563f1fe2f869?s=128

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. None
  4. None
  5. ໨త • 2tch • SwiftͰॻ͖͍ͨ • ࠷େ1000ߦͷςΩετΛॲཧ͢Δ • ΍Δ͜ͱ •

    ཁૉͷ੾Γग़͠ɾɾɾσϦϛλ<>, վߦίʔυ • HTMLಛघจࣈUnescape • ຊจͷύʔεɼϨΠΞ΢τ • 1000ݸ͋Δͱɼ1[msec/item]Ͱ΋1ඵ͔͔Δ • 30[msec]Ͱ1000ݸॲཧͰ͖Δͷ͕໨ඪ • ආ͚ΒΕͳ͍ਖ਼نදݱॲཧ͕஗͍
  6. HTMLಛघจࣈ • W3CͰఆٛ͞Ε͍ͯΔ • &<>ͳͲͷςΩετʹͦͷ··ॻ͚ͳ͍ಛघͳจࣈ • Escape/Unescapeʔ&amp; &#38; &#x26; •

    ໊લ • 10ਐ਺͋Δ͍͸16ਐ਺ͷจࣈίʔυ &amp; & escape &amp; & unescape
  7. ՝୊ • Google Toolbox • SwiftʹҠ২΋؆୯ • ଎౓͸΄ͱΜͲมΘΒͳ͍ • ͔͔ͤͬͩ͘Β଎͍ͨ͘͠

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

     Y  Y  Y  Y จࣈྻͷ·· ॲཧ  
    ※୯Ґ͸[msec] ※unescapeͷׅހ಺ͷ਺஋͸NSAttributedStringΛ࢖ͬͨࢀߟ஋
  11. ίʔυ্ͷ՝୊Λߟ͑Α͏

  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)) } ΋͸΍จࣈͰ͸ͳ͍ͷͰɼ”&”ͳͲͷจࣈίʔυσʔλ Λ͋Β͔͡Ί࡞੒͓ͯ͘͠
  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 ࣍ͷ&ͷ୳ࡧ
  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 Ϛονϯά
  15. จࣈྻͷҰகΛνΣοΫ͢Δίʔυ 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 ΋ͬͱφ΢͍ײ͡Ͱ
  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ͷܕʹ໭Γ஋ΛຒΊࠐΜͰ͓͚͹஋Λड͚औΕΔ
  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ͷ഑ྻ ίʔυ
  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ഒͣͭͯ͠଍ͤ͹Α͍
  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 ಉ͡όοϑΝ
  20. ͜ΕͩͱΫϥογϡ͠·͢

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

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

  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) จࣈྻ
  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) จࣈྻ
  28. Binary search - 38Λݟ͚ͭΔ࣌      

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

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

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

  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) จࣈྻ
  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) จࣈྻ
  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 จࣈྻ ·ͱΊͯίϐʔ
  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
  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
  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
  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 ·ͱΊͯίϐʔ
  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
  40. վߦίʔυͰ੾Γ෼͚Δͱ͖ • จࣈྻΛ[Unichar]ͷίʔυʹม׵ • [Unichar]͔Βɼ‘\n’ΛόοϑΝ͔Β୳͢ • ‘\n’Ͱғ·ΕΔ[Unichar]ͷҰ෦ΛStringʹม׵ • ޮՌ •

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

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

     Y  Y  Y  Y จࣈྻͷ·· ॲཧ  
    ※୯Ґ͸[msec] ※unescapeͷׅހ಺ͷ਺஋͸NSAttributedStringΛ࢖ͬͨࢀߟ஋
  43. ·ͱΊ • ୯७ͳจࣈྻॲཧͷߴ଎Խ • จࣈίʔυͷੜσʔλͰॲཧ͢Δ • forEachΛ్தͰྫ֎ʹൈ͚Δ • ͳΔ΂͘จࣈྻʹ͠ͳ͍ •

    վߦ΍ΧϯϚ۠੾Γͷ੾Γग़͠ʹ΋༗ޮ • ෳࡶͳॲཧ͸ఘΊͯɼਖ਼نදݱɾɾɾɾ
  44. Ͱ΋࠷ۙͷσόΠε଎͍Αʂ