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

Build時間改善

Cb417fd80478ea21c4c0cbe2e3ded4d0?s=47 Naoto Onagi
December 02, 2016

 Build時間改善

CA.swift [https://eventdots.jp/event/606151] で発表した内容になります
iOS開発において、Build時間を短くするための流れやTipsをまとめました

コードベースの改善については、以下にSample Projectを用意してあります
https://github.com/naoto0n2/BuildTimeSample/

【追記】
OTHER_SWIFT_FLAGS に -Xfrontend -debug-time-function-bodies を設定することで計測処理の分Build時間が遅くなります
計測が終わった後は外しておくことをおすすめします

Cb417fd80478ea21c4c0cbe2e3ded4d0?s=128

Naoto Onagi

December 02, 2016
Tweet

Other Decks in Technology

Transcript

  1. #VJME࣌ؒվળ 

  2. খᑎ௚ਓ<0OBHJ/BPUP> w ೥݄ʹૣظೖࣾͷ৽ଔ w "8"ͷJ04ΤϯδχΞ w IUUQTHJUIVCDPNOBPUPO ࣗݾ঺հ

  3. 4XJGUԽ

  4. #VJME͕஗͍

  5. #VJME͕஗͍ w $MFBO#VJMEͰ෼ʙ෼͔͔Δ͜ͱ΋ w ։ൃ଎౓΍ϞνϕʔγϣϯʹӨڹ

  6. w 9DPEF w .BD#PPL1SP 3FUJOB JODI .JE  w ()[*OUFM$PSFJ

    w ϝϞϦ(# ؀ڥ
  7. #VJME$PNQJMF࣌ؒΛଌΔ

  8. ϓϩδΣΫτͷ#VJME࣌ؒ EFGBVMUTXSJUFDPNBQQMFEU9DPEF4IPX#VJME0QFSBUJPO%VSBUJPO:&4 ˣ #VJME$PNQJMF࣌ؒΛଌΔ

  9. ϑΝΠϧ΍ϝιου͝ͱͷ $PNQJMF࣌ؒ YDPEFCVJMEXPSLTQBDF"QQ/BNFYDXPSLTQBDFTDIFNF"QQ/BNFDMFBO CVJME05)&3@48*'5@'-"(49GSPOUFOEEFCVHUJNFGVODUJPOCPEJFTc HSFQ<>NTcHSFQW?<>NTcTPSUOSCVJMEUJNFUYU #VJME$PNQJMF࣌ؒΛଌΔ

  10. #VJME5JNF"OBMZ[FSGPS9DPEF IUUQTHJUIVCDPN3PCFSU(VNNFTTPO#VJME5JNF"OBMZ[FSGPS9DPEF #VJME5JNF"OBMZ[FSGPS9DPEF

  11. "8"ͷ1SPKFDUͰ࣮ߦ<'JMF> #VJME5JNF"OBMZ[FSGPS9DPEF

  12. "8"ͷ1SPKFDUͰ࣮ߦ<.FUIPE> #VJME5JNF"OBMZ[FSGPS9DPEF

  13.  HJUIVC͔Β%PXOMPBE 9DPEFͰ3VO දࣔ͞ΕͨΞϓϦʹॻ͍ͯ͋ΔखॱΛ౿Ή #VJME5JNF"OBMZ[FSGPS9DPEFͷ࢖͍ํ

  14. ௐࠪର৅

  15.  #VJMEઃఆ  ࣮ࡍʹ$PNQJMF͕஗͍Օॴ  ͦͷଞ ௐࠪର৅

  16. ௐࠪର৅  #VJMEઃఆ  ࣮ࡍʹ$PNQJMF͕஗͍Օॴ  ͦͷଞ

  17. ฒྻ$PNQJMF਺

  18. ฒྻ$PNQJMF਺ ฒྻ$PNQJMF

  19. ฒྻ$PNQJMF਺ ฒྻ$PNQJMF਺Λઃఆ EFGBVMUTXSJUFDPNBQQMFEU9DPEF *%&#VJME0QFSBUJPO.BY/VNCFS0G$PODVSSFOU$PNQJMF5BTLT

  20. ฒྻ$PNQJMF਺ .BDͷ$PSF਺ TZTUFN@QSPpMFS41)BSEXBSF%BUB5ZQF )BSEXBSF )BSEXBSF0WFSWJFX  5PUBM/VNCFSPG$PSFT  .BDͷ$PSF਺ͱಉ͡ ฒྻ$PNQJMF਺ͩͱ଎͍ʢʁʣ

    ˠ
  21. ฒྻ$PNQJMF਺ ฒྻ$PNQJMF਺͝ͱͷ#VJME࣌ؒ ฒྻ$PNQJMF਺ #VJME࣌ؒ<T>      

        $PSF਺पลͷ஋Ͱ Ұ൪଎͍஋Λௐ΂͓ͯ͘ ˠ EFGBVMUTXSJUFDPNBQQMFEU9DPEF *%&#VJME0QFSBUJPO.BY/VNCFS0G$PODVSSFOU$PNQJMF5BTLT
  22. ࠷దԽઃఆ

  23. ࠷దԽઃఆ 5BSHFUˠ#VJME4FUUJOH ˠ"QQMF--7.4XJGU$PNQJMFSˠ0QUJNJ[BUJPO-FWFM %FCVH/POF<0>/POF<0OPOF> w ෆཁͳ࠷దԽΛආ͚Δ

  24. ࠷దԽઃఆ 5BSHFUˠ#VJME4FUUJOHTˠ"EE6TFS%FpOFE4FUUJOH 48*'5@8)0-&@.0%6-&@015*.*;"5*0/Λ௥Ճ %FCVH:&4

  25. ࠷దԽ݁Ռ #VJME5JNF<T> 48*'5@8)0-&@.0%6-&@015*.*;"5*0/ /P :FT ࠩ෼#VJME   $MFBO#VJME 

     w ࠩ෼#VJME͕஗͘ͳΔ w $MFBO#VJME͕େ෯ʹ଎͘ͳΔ
  26. ࠷దԽ݁Ռ #VJME5JNF<T> 48*'5@8)0-&@.0%6-&@015*.*;"5*0/ /P :FT ࠩ෼#VJME   $MFBO#VJME 

     w ࠩ෼#VJME͕஗͘ͳΔ w $MFBO#VJME͕େ෯ʹ଎͘ͳΔ ˠ
  27. ࠷దԽ݁Ռ #VJME5JNF<T> 48*'5@8)0-&@.0%6-&@015*.*;"5*0/ /P :FT ࠩ෼#VJME   $MFBO#VJME 

     w ࠩ෼#VJME͕஗͘ͳΔ w $MFBO#VJME͕େ෯ʹ଎͘ͳΔ ˠ
  28. w ฒྻ$PNQJMF਺Λ࠷దͳ஋ʹ͓ͯ͘͠ w %FCVH࣌ͷ0QUJNJ[BUJPO-FWFM͸
 /POF<0>/POF<0OPOF> w 48*'5@8)0-&@.0%6-&@015*.*;"5*0/Λ:&4ʹ
 ʢ9DPEF࣌఺ʣ #VJMEઃఆ·ͱΊ

  29. ௐࠪର৅  #VJMEઃఆ  ࣮ࡍʹ$PNQJMF͕஗͍Օॴ  ͦͷଞ

  30. $PNQJMF࣌ؒͷվળ

  31. Կނ஗͍ͷ͔ʁ

  32. Կނ஗͍ͷ͔ʁ ˠ͍͍ͩͨܕਪ࿦ͷ͍ͤ

  33. վળ͢ΔͨΊͷྲྀΕ  ஗͍NFUIPE͔Β
 ܕ৘ใ͕଍Γͯແͦ͞͏ͳՕॴΛਪଌ  ॻ͖׵͑ͯΈΔ  ʙΛ܁Γฦ͢ $PNQJMF࣌ؒͷվળ

  34. ྫ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  35. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  36. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ ஗͗͢ΔͷͰ࣮૷ΛݟΔ

  37. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func lateMethod(type: SampleType, text: String?) -> String { switch

    type { case .type1: return "1: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type2: return "2: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type3: return "3: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type4: return "4: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type5: return "5: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") } } enum SampleType: String { case type1 = "type1" case type2 = "type2" case type3 = "type3" case type4 = "type4" case type5 = "type5" } private func generateText() -> String? { return (arc4random() % 2 == 0) ? "text" : nil }
  38. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func lateMethod(type: SampleType, text: String?) -> String { switch

    type { case .type1: return "1: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type2: return "2: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type3: return "3: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type4: return "4: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") case .type5: return "5: Hoge " + (self.generateText() ?? "nil") + " Fuga " + type.rawValue + " " + (text ?? "nil") } } enum SampleType: String { case type1 = "type1" case type2 = "type2" case type3 = "type3" case type4 = "type4" case type5 = "type5" } private func generateText() -> String? { return (arc4random() % 2 == 0) ? "text" : nil } ˣ NT
  39. ಛ௃Λ͔ͭΉ  จࣈྻΛ ԋࢉࢠͰ݁߹  </JM$PBMFTDJOH0QFSBUPS> ɹɹɹɹɹˣ ૬ੑ͕ѱ͍ͷ͔΋͠Εͳ͍ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  40.  ԋࢉࢠʹΑΔ݁߹Λ΍ΊΔ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func fastMethod1(type: SampleType, text: String?) -> String

    { switch type { case .type1: return "1: Hoge \(self.generateText() ?? "nil") Fuga \(type.rawValue) \(text ?? "nil")" … } }
  41.  ԋࢉࢠʹΑΔ݁߹Λ΍ΊΔ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func fastMethod1(type: SampleType, text: String?) -> String

    { switch type { case .type1: return "1: Hoge \(self.generateText() ?? "nil") Fuga \(type.rawValue) \(text ?? "nil")" … } } NTˠNT
  42.  ॲཧΛࣄલʹߦ͏ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func fastMethod2(type: SampleType, text: String?) -> String

    { let text = text ?? "nil" switch type { case .type1: let generatedText = self.generateText() ?? "nil" return "1: Hoge " + generatedText + " Fuga " + type.rawValue + " " + text … } }
  43.  ॲཧΛࣄલʹߦ͏ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ NTˠNT func fastMethod2(type: SampleType, text: String?) ->

    String { let text = text ?? "nil" switch type { case .type1: let generatedText = self.generateText() ?? "nil" return "1: Hoge " + generatedText + " Fuga " + type.rawValue + " " + text … } }
  44. ͳΔ΂͘ૣ͍ஈ֊Ͱ
 ܕΛ֬ఆͤ͞Δ͜ͱ͕େࣄ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  45. ྫ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  46. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func lateMethod(data: Data) { self.log(data: [ "userId": data.user?.id ??

    "userId", "userName:": data.user?.name ?? "userName", "errorCodeString": "\(data.errorCode)", "description": data.description ?? "Description" ]) } struct Data { let user: User? let errorCode: Int let description: String? } struct User { let id: String? let name: String? } private func log(data: [String: Any]) { // Send log data to server } NT
  47. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ NT ಛ௃  Ҿ਺Λ౉࣌͢௚઀%JDUJPOBSZΛੜ੒  Λ%JDUJPOBSZͷWBMVFࢦఆ࣌ʹ࢖༻ func lateMethod(data: Data)

    { self.log(data: [ "userId": data.user?.id ?? "userId", "userName:": data.user?.name ?? "userName", "errorCodeString": "\(data.errorCode)", "description": data.description ?? "Description" ]) } struct Data { let user: User? let errorCode: Int let description: String? } struct User { let id: String? let name: String? } private func log(data: [String: Any]) { // Send log data to server }
  48. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func fastMethod(data: Data) { let userId = data.user?.id ??

    "userId" let userName = data.user?.name ?? "userName" let errorCodeString = "\(data.errorCode)" let description = data.description ?? "Description" let data = [ "userId": userId, "userName:": userName, "errorCodeString": errorCodeString, "description": description ] self.log(data: data) } ˠ NT NT func lateMethod(data: Data) { self.log(data: [ "userId": data.user?.id ?? "userId", "userName:": data.user?.name ?? "userName", "errorCodeString": "\(data.errorCode)", "description": data.description ?? "Description" ]) } struct Data { let user: User? let errorCode: Int let description: String? } struct User { let id: String? let name: String? } private func log(data: [String: Any]) { // Send log data to server }
  49. ྫ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  50. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func lateMethod(size: CGSize) -> CGSize { return CGSize( width:

    size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10, height: size.height) } var view1: UIView? var view2: UIView? NT
  51. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func lateMethod(size: CGSize) -> CGSize { return CGSize( width:

    size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10, height: size.height) } var view1: UIView? var view2: UIView? NT ಛ௃  $(4J[FJOJUJBMJ[FSͷҾ਺ʹ௚઀ෳࡶͳࣜ  $('MPBUͱܕ͕ෆ໌ྎͳ਺஋ͷࠞࡏ
  52. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ func lateMethod(size: CGSize) -> CGSize { return CGSize( width:

    size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10, height: size.height) } var view1: UIView? var view2: UIView? NT func fastMethod2(size: CGSize) -> CGSize { let view1Width: CGFloat = view1?.bounds.width ?? 0 let view2Width: CGFloat = view2?.bounds.width ?? 0 let newWidth: CGFloat = size.width + view1Width + view2Width + 10 return CGSize(width: newWidth, height: size.height) } ˠ NT
  53. $PNQJMFSతʹ͸ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  54. size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) +

    10 ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ
  55. size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) +

    10 ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ $('MPBU $('MPBU
  56. size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) +

    10 ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10 $('MPBU $('MPBU $('MPBU $('MPBU $('MPBU ˣ
  57. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0)

    + 10 $('MPBU $('MPBU size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10 $('MPBU public func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat ˣ
  58. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0)

    + 10 public func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10 $('MPBU ˣ
  59. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0)

    + 10 $('MPBU size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10 public func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat ˣ
  60. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0)

    + 10 public func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat size.width + (view1?.bounds.width ?? 0) + (view2?.bounds.width ?? 0) + 10 $('MPBU ˣ
  61. $PNQJMFSͷؾ࣋ͪʹͳͬͯ ܕ৘ใΛ༩͑ͯ͋͛Δ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ

  62. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ let newWidth: CGFloat = size.width + view1Width + view2Width

    + 10
  63. ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ let newWidth: CGFloat = size.width + view1Width + view2Width

    + 10 ˣ let newWidth: CGFloat = size.width + view1Width + view2Width + 10 $('MPBU $('MPBU $('MPBU $('MPBU $('MPBU
  64. w $PNQJMFS͕͙͢ਪ࿦Ͱ͖ΔΑ͏ܕ৘ใΛ༩͑Δ w ಛʹ Λ࢖͏ͱ͖͸ద੾ʹܕΛࢦఆ w ߦͰԋࢉࢠʹΑΔ݁߹Λ͗͢͠ͳ͍ w ܕਪ࿦͕଎͍ˠγϯλοΫεϋΠϥΠτ΋଎͍ w

    'VODUJPOBM1SPHSBNNJOHͰى͖͕ͪͳγϯλοΫεϋΠϥΠτ͕
 ஗͍ݱ৅Λճආ͢Δ͜ͱ΋ w ͨͩ͠ʮਪ࿦͠΍͢͞ʯͱʮ4XJGUZͳίʔυʯ͸
 τϨʔυΦϑͳ͜ͱ͕ଟ͍ w ݦஶʹ஗͍ՕॴͷΈͷվળͰे෼ ܕਪ࿦ʹ͕͔͔࣌ؒΔύλʔϯ·ͱΊ
  65. "8"ͰͷϏϑΥʔɾΞϑλʔ 'JMF$PNQJMF5JNF<NT>

  66. "8"ͰͷϏϑΥʔɾΞϑλʔ 'JMF$PNQJMF5JNF<NT>

  67. ௐࠪର৅  #VJMEઃఆ  ࣮ࡍʹ$PNQJMF͕஗͍Օॴ  ͦͷଞ

  68. E4:.'JMF

  69. w %FCVH4ZNCPM'JMF w $SBTIϩάΛ௥͏ҝʹඞཁ %FCVH#VJMEͰෆཁͳ৔߹͸%8"3' ˠʙඵ୹ॖ E4:.'JMF

  70. #VJME%FWJDF

  71. (FOFSJDJ04%FWJDFΛબ୒ͯ͠#VJME͢Δͱ஗͍ ˣ ಛʹཧ༝͕ͳ͚Ε͹࣮ػ͔4JNVMBUPSΛબ୒ #VJME%FWJDF 4JNVMBUPS (FOFSJD J04%FWJDF #VJME5JNF<T>  

  72.  ࣮ࡍʹ$PNQJMF͕஗͍Օॴ ˠ$PNQJMFSͷܕਪ࿦Λखॿ͚ͯ͋͛͠Δ  #VJMEઃఆ ˠฒྻ$PNQJMF਺ɺ࠷దԽઃఆΛݟ௚͢  ͦͷଞ ˠE4:. #VJME%FWJDF

  73. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠