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

F9feb45c0a049cccc3e2563f1fe2f869?s=47 sonson
September 18, 2017

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

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

F9feb45c0a049cccc3e2563f1fe2f869?s=128

sonson

September 18, 2017
Tweet

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. Ͱ΋࠷ۙͷσόΠε଎͍Αʂ