स्विफ्ट संकलन समय इतना धीमा क्यों है?


210

मैं Xcode 6 बीटा 6 का उपयोग कर रहा हूं।

यह कुछ ऐसा है जो मुझे पिछले कुछ समय से परेशान कर रहा है, लेकिन यह उस बिंदु पर पहुंच रहा है जहां अब यह मुश्किल से उपयोग योग्य है।

मेरी परियोजना में 65 स्विफ्ट फ़ाइलों और कुछ ब्रिजित ऑब्जेक्टिव-सी फ़ाइलों का एक सभ्य आकार होना शुरू हो रहा है (जो वास्तव में समस्या का कारण नहीं हैं)।

यह किसी भी स्विफ्ट फ़ाइल के लिए किसी भी मामूली संशोधन की तरह लगता है (जैसे कि क्लास में एक साधारण सफेद स्थान जोड़ना जो कि ऐप में मुश्किल से उपयोग किया जाता है) पूरे स्विफ्ट फ़ाइलों को फिर से निर्दिष्ट करने के लिए प्रेरित करेगा।

एक गहरी जांच के बाद, मैंने पाया है कि संकलक समय का 100% हिस्सा क्या ले रहा है, वह CompileSwiftचरण है जहां Xcode swiftcआपके लक्ष्य की सभी स्विफ्ट फ़ाइलों पर कमांड चलाता है ।

मैंने कुछ और जांच की, और अगर मैं केवल एक डिफ़ॉल्ट नियंत्रक के साथ एप्लिकेशन प्रतिनिधि को रखता हूं, तो संकलन बहुत तेज है, लेकिन जैसा कि मैं अपनी परियोजना फाइलों में अधिक से अधिक जोड़ रहा था, संकलन समय वास्तव में धीमा होने लगा था।

अब केवल 65 स्रोत फ़ाइलों के साथ, हर बार संकलित करने में लगभग 8/10 सेकंड लगते हैं। बहुत तेज नहीं है ।

मैं किसी भी पद को छोड़कर इस मुद्दे के बारे में बात नहीं देखा है इस एक है, लेकिन तो मैं सोच रहा हूँ अगर मैं केवल उस मामले में एक हूँ यह Xcode 6. के एक पुराने संस्करण था।

अपडेट करें

मैंने GitHub पर Alamofire , Euler और CryptoSwift जैसी कुछ Swift परियोजनाओं की जाँच की है , लेकिन उनमें से किसी के पास वास्तव में तुलना करने के लिए पर्याप्त Swift फाइलें नहीं थीं। एकमात्र परियोजना जो मैंने पाया कि एक सभ्य आकार शुरू हो रहा था स्विफ्टएचएन था , और भले ही इसके पास केवल एक दर्जन स्रोत फाइलें थीं, मैं अभी भी एक ही चीज़ को सत्यापित करने में सक्षम था, एक साधारण स्थान और पूरे प्रोजेक्ट को पुनर्संयोजन की आवश्यकता थी जो एक को लेना शुरू कर रहा था थोड़ा समय (2/3 सेकंड)।

ऑब्जेक्टिव-सी कोड की तुलना में जहां विश्लेषक और संकलन दोनों तेजी से धधक रहे हैं, यह वास्तव में ऐसा लगता है कि स्विफ्ट कभी भी बड़ी परियोजनाओं को संभालने में सक्षम नहीं होगा, लेकिन कृपया मुझे बताएं कि मैं गलत हूं।

एक्सकोड 6 बीटा 7 के साथ अद्यतन

फिर भी कोई सुधार नहीं हुआ। यह हास्यास्पद होने लगा है। की कमी के साथ#importस्विफ्ट , मैं वास्तव में यह नहीं देखता कि एप्पल कभी भी इसे कैसे अनुकूलित कर पाएगा।

एक्सकोड 6.3 और स्विफ्ट 1.2 के साथ अपडेट करें

Apple ने वृद्धिशील बिल्ड (और कई अन्य संकलक अनुकूलन) जोड़े हैं । आपको उन लाभों को देखने के लिए स्विफ्ट 1.2 में अपना कोड माइग्रेट करना होगा, लेकिन Apple ने ऐसा करने में आपकी मदद करने के लिए Xcode 6.3 में एक टूल जोड़ा:

यहां छवि विवरण दर्ज करें

तथापि

जैसा मैंने किया था, वैसे ही जल्दी से आनन्द मत लो। ग्राफ वृद्धि बनाने के लिए वे जिस ग्राफ सॉल्वर का उपयोग करते हैं, वह अभी तक बहुत अच्छी तरह से अनुकूलित नहीं है।

वास्तव में सबसे पहले, यह फ़ंक्शन हस्ताक्षर परिवर्तनों को नहीं देखता है, इसलिए यदि आप एक विधि के ब्लॉक में एक स्थान जोड़ते हैं, तो उस वर्ग के आधार पर सभी फाइलें फिर से तैयार की जाएंगी।

दूसरा, यह उन फ़ाइलों के आधार पर पेड़ को बनाने के लिए लगता है जो एक बदलाव को प्रभावित नहीं करता है, भले ही पुन: संकलित किया गया हो। उदाहरण के लिए, यदि आप इन तीन वर्गों को विभिन्न फाइलों में स्थानांतरित करते हैं

class FileA: NSObject {
    var foo:String?
}
class FileB: NSObject {
    var bar:FileA?
}
class FileC: NSObject {
    var baz:FileB?
}

अब यदि आप संशोधित करते हैं FileA, तो संकलक स्पष्ट रूप FileAसे पुन: संकलित होने के लिए चिह्नित करेगा । यह भी recompile होगा FileB(जो कि परिवर्तनों के आधार पर ठीक होगा FileA), लेकिन यह भी FileCक्योंकि FileBrecompiled है, और यह बहुत बुरा है क्योंकि यहाँ FileCकभी उपयोग नहीं होता FileAहै।

इसलिए मुझे आशा है कि वे उस निर्भरता के पेड़ के तलवे में सुधार करेंगे ... मैंने इस नमूना कोड के साथ एक रडार खोला है ।

Xcode 7 बीटा 5 और स्विफ्ट 2.0 के साथ अद्यतन

कल Apple ने बीटा 5 जारी किया और रिलीज़ नोटों के अंदर हम देख सकते हैं:

स्विफ्ट लैंग्वेज एंड कंपाइलर • इंक्रीमेंटल बिल्ड: केवल एक फंक्शन की बॉडी बदलने से डिपेंडेंट फाइल्स को फिर से नहीं बनाना चाहिए। (15352929)

मैंने इसे एक कोशिश दी है और मुझे यह कहना चाहिए कि यह अब वास्तव में (वास्तव में!) काम कर रहा है। वे काफी तेजी से वृद्धिशील बिल्ड को अनुकूलित करते हैं।

मैं आपको एक swift2.0शाखा बनाने और अपने कोड को XCode 7 बीटा 5 का उपयोग करने की तारीख तक रखने की सलाह देता हूं । आप संकलक के संवर्द्धन से प्रसन्न होंगे (हालांकि मैं कहूंगा कि XCode 7 की वैश्विक स्थिति अभी भी धीमी और छोटी है)

एक्सकोड 8.2 के साथ अद्यतन

इस मुद्दे पर मेरे अंतिम अपडेट के बाद से कुछ समय हो गया है इसलिए यहां यह है।

हमारा ऐप अब लगभग विशेष रूप से स्विफ्ट कोड की 20k लाइनों के बारे में है, जो सभ्य है, लेकिन उत्कृष्ट नहीं है। यह स्विफ्ट 2 और स्विफ्ट 3 माइग्रेशन से कम हुआ। 2014 के मैकबुक प्रो (2.5 गीगाहर्ट्ज इंटेल कोर i7) पर संकलन करने के लिए लगभग 5/6 मी का समय लगता है जो एक साफ बिल्ड पर ठीक है।

हालाँकि वृद्धिशील निर्माण Apple का दावा करने के बावजूद अभी भी एक मजाक है:

केवल छोटे परिवर्तन होने पर Xcode पूरे लक्ष्य का पुनर्निर्माण नहीं करेगा। (28892475)

जाहिर है मुझे लगता है कि हममें से कई लोग इस बकवास की जाँच करने के बाद हँसे (एक निजी (निजी!) संपत्ति को मेरी परियोजना की किसी भी फ़ाइल में जोड़कर पूरी बात को फिर से जोड़ दिया जाएगा ...)

मैं आप लोगों को Apple डेवलपर मंचों पर इस धागे की ओर संकेत करना चाहता हूं जिसमें इस मुद्दे के बारे में कुछ और जानकारी है (साथ ही इस मामले में Apple देव संचार की एक बार में सराहना की गई है)

मूल रूप से लोग वृद्धिशील निर्माण में सुधार करने के लिए कुछ चीजें लेकर आए हैं:

  1. HEADER_MAP_USES_VFSसेट करने के लिए एक प्रोजेक्ट सेटिंग जोड़ेंtrue
  2. Find implicit dependenciesअपनी योजना से अक्षम करें
  3. एक नया प्रोजेक्ट बनाएं और अपनी फ़ाइलों को पदानुक्रम को नए पर ले जाएं।

मैं 3 समाधान की कोशिश करूंगा, लेकिन समाधान 1/2 हमारे लिए काम नहीं किया।

इस पूरी स्थिति में विडंबना यह है कि इस मुद्दे पर पहली पोस्ट को देखकर हम Xcode 6 का उपयोग कर रहे थे, जिसके बारे में मेरा मानना ​​है कि स्विफ्ट 1 या स्विफ्ट 1.1 कोड तब था जब हम पहले संकलन की सुस्ती तक पहुँच गए थे और अब लगभग दो साल बाद Apple के वास्तविक सुधारों के बावजूद। स्थिति बस के रूप में Xcode 6 के साथ के रूप में बुरा है। कितना विडंबना है।

मैं वास्तव में वास्तव में हमारी परियोजना के लिए Obj / C पर स्विफ्ट चुनने के लिए पछतावा करता क्योंकि इसमें दैनिक हताशा शामिल है। (मैं AppCode पर भी स्विच करता हूं लेकिन यह एक और कहानी है)

वैसे भी मैं इस SO पोस्ट को 32k + व्यूज और 143 अप इस लेखन के रूप में देखता हूं इसलिए मुझे लगता है कि मैं अकेला नहीं हूं। इस स्थिति पर निराशावादी होने के बावजूद लोगों को लटकाएं सुरंग के अंत में कुछ प्रकाश हो सकता है।

यदि आपके पास समय (और साहस!) है तो मुझे लगता है कि Apple इस बारे में रडार का स्वागत करता है।

अगली बार तिल! चियर्स

एक्सकोड 9 के साथ अद्यतन

इस पर ठोकर आज। Xcode चुपचाप वर्तमान भयानक प्रदर्शन पर सुधार करने के लिए एक नया निर्माण प्रणाली शुरू की। आपको इसे कार्यक्षेत्र सेटिंग्स के माध्यम से सक्षम करना होगा।

यहां छवि विवरण दर्ज करें

अभी तक एक कोशिश दे चुके हैं, लेकिन इस पोस्ट को पूरा करने के बाद इसे अपडेट करेंगे। हालांकि होनहार लग रहा है।


1
दिलचस्प! मुझे आश्चर्य है कि अगर यह सिर्फ एक लापता अनुकूलन है या इतनी फ़ाइलों को पार्स करने की आवश्यकता है क्योंकि कोई इंटरफ़ेस फ़ाइलें नहीं हैं।
ज़ाफ

2
इसी तरह के मुद्दे थे, और अंत में मुझे एहसास हुआ कि यह JSON से छूटने के लिए इकाई वर्गों में उपयोग किए जाने वाले कस्टम ऑपरेटरों के कारण था। यदि आप किसी का उपयोग कर रहे हैं, तो मैं आपको सुझाव देता हूं कि एक-एक करके सामान्य फ़ंक्शन में परिवर्तित करने का प्रयास करें और देखें कि क्या कुछ बदलता है।
एंटोनियो

4
संकलन XCode 6 बीटा 6 के बाद से मेरी परियोजना में दांत पीसने वाला धीमा हो गया है। मुझे यकीन नहीं है कि यह बीटा में परिवर्तन के कारण है या मेरे कोड के कारण है। लेकिन मेरी परियोजना अभी भी बड़ी नहीं है (~ 40-50 स्विफ्ट फाइलें)।
बैडमिंटनकैट

2
मेरी परियोजना के विकसित होते ही संकलन असहनीय रूप से धीमा हो गया है। मैं कई पॉड्स पर भी निर्भर करता हूं, जो मुझे यकीन है कि इस मुद्दे को बढ़ा देगा। यह हाल के गैर-बीटा रिलीज़ का उपयोग कर रहा है।
एंडी

2
वृद्धिशील निर्माण अभी भी "रूढ़िवादी निर्भरता विश्लेषण" में किया गया है, इसलिए आप अभी भी आवश्यकता से अधिक फ़ाइलों को पुनर्निर्माण कर सकते हैं। उम्मीद है, समय के साथ इसमें सुधार होगा।
nmdias

जवाबों:


70

खैर, यह पता चला कि रोब नेपियर सही था। यह एक एकल फ़ाइल (वास्तव में एक विधि) थी जो कंपाइलर को बेरज़ेक जाने के लिए प्रेरित कर रही थी।

अब मुझे गलत मत समझो स्विफ्ट हर बार आपकी सभी फाइलों को फिर से जोड़ देती है, लेकिन अब बड़ी बात यह है कि Apple ने जो फाइल संकलित की है, उस पर रियल-टाइम संकलन फीडबैक जोड़ा गया है, इसलिए अब Xcode 6 GM दिखाता है कि स्विफ्ट फाइलें संकलित की जा रही हैं और वास्तविक समय में संकलन की स्थिति। जैसा कि आप इस स्क्रीनशॉट में देख सकते हैं:

यहां छवि विवरण दर्ज करें

इसलिए यह जानना बहुत आसान है कि आपकी कौन सी फाइल इतनी लंबी है। मेरे मामले में यह कोड का टुकड़ा था:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : self.title ?? ""
        ])

return dic.copy() as NSDictionary

क्योंकि संपत्ति titleप्रकार की थी var title:String?और नहीं NSString। इसे जोड़ने पर कंपाइलर पागल हो रहा था NSMutableDictionary

इसे बदलना:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : NSString(string: self.title ?? "")
        ])

return dic.copy() as NSDictionary

संकलन 10/15 सेकंड से चला गया (शायद और भी अधिक) एक सेकंड के लिए नीचे ... अद्भुत।


3
जवाब के साथ आने के लिए धन्यवाद। यह उन लोगों के लिए बहुत उपयोगी हो सकता है, जो संकलन के दौरान टाइप-इनविज़न इंजन से टकरा जाते हैं।
रोब नेपियर

1
आपको यह दृश्य @apouche कहाँ से मिला? मैं इसे xcode में नहीं देखता
एरिक

2
आपको डिबग सहायक (CMD + 8) को खोलने और वर्तमान बिल्ड पर क्लिक करने की आवश्यकता है
apouche

1
हाँ, मुझे यकीन है कि Apple इसे बाद में ऑप्टिमाइज़ करेगा, अन्यथा स्विफ्ट में रियल वर्ल्ड प्रोजेक्ट्स को यहीं और वहाँ पर डूम किया जाता है।
अपूचे

1
मैं इस उपकरण को कैसे प्राप्त कर सकता हूं जो दिखाता है कि कौन सी फाइलें संकलित की जा रही हैं?
jgvb

42

हमने इससे निपटने के लिए काफी कुछ करने की कोशिश की है क्योंकि हमारे पास स्विफ्ट कोड की लगभग 100k लाइनें और ObjC कोड की 300k लाइनें हैं।

हमारा पहला कदम फंक्शन कम्पाइल टाइम आउटपुट के अनुसार सभी फंक्शन्स को ऑप्टिमाइज़ करना था (जैसे कि यहाँ वर्णित https://thatthinginswift.com/debug-long-compile-times-swift/ )

आगे हमने सभी स्विफ्ट फ़ाइलों को एक फ़ाइल में मर्ज करने के लिए एक स्क्रिप्ट लिखी, इससे एक्सेस स्तर टूट जाता है लेकिन यह हमारे संकलित समय को 5-6min से ~ 1 मिनट तक ले आया।

यह अब दोषपूर्ण है क्योंकि हमने Apple से इस बारे में पूछा था और उन्होंने सलाह दी कि हमें निम्नलिखित कार्य करने चाहिए:

  1. 'स्विफ्ट कंपाइलर - कोड जनरेशन' बिल्ड सेटिंग में 'पूरे मॉड्यूल ऑप्टिमाइज़ेशन' को चालू करें। चुनते हैं'Fast, Whole Module Optimization'

यहां छवि विवरण दर्ज करें

  1. 'स्विफ्ट कंपाइलर - कस्टम फ्लैग' में, आपके विकास के लिए, जोड़ते हैं '-Onone'

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

जब ये ध्वज सेट हो जाते हैं, तो संकलक सभी स्विफ्ट फ़ाइलों को एक चरण में संकलित करेगा। हमने अपनी मर्ज स्क्रिप्ट के साथ पाया यह व्यक्तिगत रूप से फ़ाइलों को संकलित करने की तुलना में बहुत तेज है। हालांकि, बिना '-Onone' ओवरराइड के , यह पूरे मॉड्यूल को भी ऑप्टिमाइज़ करेगा, जो धीमा है। जब हम '-Onone'ध्वज को दूसरे स्विफ्ट झंडे में सेट करते हैं , तो यह अनुकूलन बंद कर देता है, लेकिन यह सभी स्विफ्ट फ़ाइलों को एक चरण में संकलित करना बंद नहीं करता है।

संपूर्ण मॉड्यूल अनुकूलन के बारे में अधिक जानकारी के लिए, Apple के ब्लॉग पोस्ट को यहां देखें - https://swift.org/blog/whole-module-options//

हमने पाया है कि ये सेटिंग्स 30 सेकंड में हमारे स्विफ्ट कोड को संकलित करने की अनुमति देती हैं :-) मेरे पास इस बात का कोई सबूत नहीं है कि यह अन्य परियोजनाओं पर कैसे काम करेगा, लेकिन मैं सुझाव देता हूं कि यदि स्विफ्ट संकलन समय आपके लिए अभी भी एक मुद्दा है।

अपने ऐप स्टोर के लिए नोट बनाता है, आपको '-Onone'झंडा छोड़ देना चाहिए , क्योंकि उत्पादन बिल्ड के लिए अनुकूलन की सिफारिश की जाती है।


4
इस सलाह के लिए बहुत बहुत धन्यवाद! मुझे आसानी से समझ में नहीं आया कि आधिकारिक स्रोतों में ऐसा कुछ भी क्यों नहीं है (कम से कम खोजने में आसान), उदाहरण के लिए आपके द्वारा उल्लिखित लेख के बारे में टिप्पणी (होनी चाहिए!) -Onone। हम अभी तक पूरे मॉड्यूल ऑप्टिमाइज़ेशन का उपयोग नहीं कर सकते क्योंकि यह कंपाइलर क्रैश बनाता है ... लेकिन आपकी सलाह हमारी बिल्ड गति को लगभग x10 बढ़ावा देती है। मैकबुक एयर (वार्षिक 2013) पर यह लगभग 8 मिनट का निर्माण कर रहा था, अब यह लगभग 1 मिनट के लिए नीचे है और उस समय के आधे समय के दौरान यह लक्ष्य (हम ऐप, एक्सटेंशन और कुछ इन-हाउस फ्रेमवर्क) और संकलन स्टोरीबोर्ड्स के बीच स्विच करने में खर्च करते हैं
इल्या चुक्का

मैंने इस विधि का परीक्षण भी किया है और यह केवल विधि का उल्लेख है जिसमें -one शामिल है और यह निर्माण समय को काफी कम करता है।
Vlad

मेरे साथ भी काम करो। -Ononeबिल्ड समय को कम करने के लिए मदद का उपयोग करना । बहुत बहुत धन्यवाद दोस्त!
nahung89

34

यह आपके प्रोजेक्ट के आकार के साथ बहुत कम है। यह शायद कोड का कुछ विशिष्ट टुकड़ा है, संभवतः केवल एक पंक्ति भी। आप पूरी परियोजना के बजाय एक बार में एक फ़ाइल संकलित करने का प्रयास करके इसका परीक्षण कर सकते हैं। या बिल्ड लॉग देखने की कोशिश करें कि कौन सी फाइल में कितना समय लग रहा है।

कोड के प्रकार के एक उदाहरण के रूप में जो परेशानी का कारण बन सकता है, यह 38-लाइन गिस्ट बीटा 7 में संकलित होने में एक मिनट से अधिक समय लेता है। यह सब इस एक ब्लॉक के कारण होता है:

let pipeResult =
seq |> filter~~ { $0 % 2 == 0 }
  |> sorted~~ { $1 < $0 }
  |> map~~ { $0.description }
  |> joinedWithCommas

सरल करें कि सिर्फ एक या दो पंक्ति और यह लगभग तुरंत संकलित करता है। इस बारे में कुछ परेशानी है कि कंपाइलर में घातीय वृद्धि (संभवतः तथ्यात्मक वृद्धि) हो रही है। जाहिर है कि यह आदर्श नहीं है, और यदि आप ऐसी स्थितियों को अलग कर सकते हैं, तो आपको उन मुद्दों को साफ करने में मदद करने के लिए राडार खोलना चाहिए।


मुझे यकीन नहीं है कि आपने CompileSwiftचरण के संबंध में मेरी टिप्पणी देखी । यह सभी स्विफ्ट फ़ाइलों को लेता है, भले ही केवल एक ही संशोधित किया गया हो। इसलिए यदि यह एक ऐसी फ़ाइल है जिसमें कुछ समय लग रहा है (जो मुझे अत्यधिक संदेह है), तो कंपाइलर आपको कभी नहीं बताएगा कि यह कौन सा है।
Apouche

10
आप यह देखने के लिए व्यक्तिगत फ़ाइलों का संकलन कर सकते swiftcहैं कि वे कितनी देर तक चलती हैं।
रोब नेपियर

मैं आपको इनाम न देने के लिए माफी चाहता हूं क्योंकि मैं इसे पहले नहीं मानता। मैंने एक-एक करके फाइलें संकलित करने की भी कोशिश की, लेकिन ऐसा करना बोझिल था (हर बार सही तरीके से और रूपरेखाओं को देना था) इसलिए मैंने हार मान ली। कृपया इस पोस्ट के लिए मेरे नवीनतम उत्तर को पूर्ण विवरण के लिए देखें
Apouche

मुझे नहीं लगता कि यह प्रोजेक्ट आकार आधारित है। मेरी परियोजना में केवल 4 स्विफ्ट फाइलें हैं और अचानक अविश्वसनीय धीमी गति से संकलन शुरू कर दिया है। कल तेज रोशनी कर रहा था। विशेष रूप से ऐड आइकन और लॉन्च छवियों को छोड़कर मैंने अपनी परियोजना पर अपनी उंगली नहीं डाली।
ट्रैविस एम।

33

यदि आप विशिष्ट फ़ाइलों की पहचान करने की कोशिश कर रहे हैं जो आपके संकलन समय को धीमा कर देते हैं, तो आप इसे xctool के माध्यम से अपनी कमांड लाइन से संकलित करने का प्रयास कर सकते हैं जो आपको फ़ाइल द्वारा संकलन समय फ़ाइल देगा।

ध्यान देने वाली बात यह है कि, डिफ़ॉल्ट रूप से, यह प्रत्येक सीपीयू कोर के अनुसार 2 फाइलें समवर्ती बनाता है, और आपको "नेट" बीता हुआ समय नहीं देगा, लेकिन पूर्ण "उपयोगकर्ता" समय। इस तरह सभी समांतर फ़ाइलों के बीच भी समयावधि समाप्त हो जाती है और बहुत समान दिखाई देती है।

इसे दूर करने के लिए, ध्वज को 1 पर सेट करें-jobs , ताकि यह फ़ाइल बिल्ड को समानांतर न करे। इसमें अधिक समय लगेगा, लेकिन अंत में आपके पास "नेट" संकलन समय होगा जो आप फ़ाइल द्वारा फ़ाइल की तुलना कर सकते हैं।

यह एक उदाहरण कमांड है जिसे ट्रिक करना चाहिए:

xctool -workspace <your_workspace> -scheme <your_scheme> -jobs 1 build

"कंपाइल स्विफ्ट फाइल्स" चरण का आउटपुट कुछ इस तरह होगा:

...Compile EntityObserver.swift (1623 ms)Compile Session.swift (1526 ms)Compile SearchComposer.swift (1556 ms)
...

इस आउटपुट से आप शीघ्रता से पहचान सकते हैं कि कौन सी फाइलें संकलित होने में दूसरों की तुलना में अधिक समय ले रही हैं। इसके अलावा, आप उच्च सटीकता के साथ निर्धारित कर सकते हैं कि क्या आपके रिफैक्टरिंग (स्पष्ट जाति, प्रकार के संकेत, आदि ...) विशिष्ट फ़ाइलों के लिए संकलन समय कम कर रहे हैं या नहीं।

नोट: तकनीकी रूप से आप इसे भी कर सकते हैं xcodebuildलेकिन उत्पादन अविश्वसनीय रूप से क्रियाशील है और उपभोग करने में कठिन है।


1
बस सुनिश्चित करें कि आपके पास अपने प्रोजेक्ट का पूरा मॉड्यूल ऑप्टिमाइज़ेशन गलत पर सेट है, या यह अलग-अलग स्विफ्ट फ़ाइलों को अलग नहीं करेगा।
सबस

1
देखें Swift Compiler→ के Optimization LevelलिएFast, Whole Module Optimization [-O -whole-module-optimization]
मैट

26

मेरे मामले में, Xcode 7 में कोई अंतर नहीं था। संकलन करने के लिए मुझे कई सेकंड की आवश्यकता होती है।

उदाहरण

// Build time: 5238.3ms
return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height)

वैकल्पिकों को हटाने के बाद, निर्माण समय 99.4% कम हो गया

// Build time: 32.4ms
var padding: CGFloat = 22
if let rightView = rightView {
    padding += rightView.bounds.width
}

if let leftView = leftView {
    padding += leftView.bounds.width
}
return CGSizeMake(size.width + padding, bounds.height)

इस पोस्ट और इस पोस्ट में और अधिक उदाहरण देखें ।

Xcode के लिए समय विश्लेषक बनाएँ

मैंने एक Xcode प्लग-इन विकसित किया है, जो इन मुद्दों का अनुभव करने वाले किसी भी व्यक्ति के काम आ सकता है।

छवि

प्रतीत होता है कि स्विफ्ट 3 में सुधार आ रहा है, इसलिए उम्मीद है कि हम अपना स्विफ्ट कोड तब देखेंगे।


बहुत बढ़िया, आशा है कि मैं आपको +1 से अधिक दे सकता हूं। आप सही हैं और आपका प्लगइन बहुत अच्छा है। मैंने उसका उपयोग किया है और मेरा निर्माण समय गिरा जा रहा है, जिसका अर्थ है सुपर फास्ट डेवलपमेंट क्योंकि यह वैकल्पिक कभी-कभी बुरे होते हैं और संकलक को धीमा कर देते हैं।
हार्डिकदेविओस

बहुत खुबस ! आपका टूल मुझे बहुत मदद करता है। धन्यवाद
फिल

महान प्लगइन - वास्तव में उपयोगी! धन्यवाद
365SplendidSuns

@ रोबर्ट गुम्मेसन, क्या हमारे पास ऑब्जेक्टिव-सी कोड के लिए कोई उपकरण है?
अशोक

19

संभवतः हम स्विफ्ट कंपाइलर को ठीक नहीं कर सकते हैं, लेकिन हम जो कुछ ठीक कर सकते हैं वह है हमारा कोड!

स्विफ्ट कंपाइलर में एक छिपा हुआ विकल्प है जो सटीक समय अंतराल को प्रिंट करता है जो कंपाइलर हर एक फ़ंक्शन को संकलित करने के लिए लेता है -Xfrontend -debug-time-function-bodies:। यह हमारे कोड में बाधाओं को खोजने और संकलन समय में महत्वपूर्ण सुधार करने की अनुमति देता है।

टर्मिनल में निम्नलिखित को सरल बनाएं और परिणामों का विश्लेषण करें:

xcodebuild -workspace App.xcworkspace -scheme App clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt

बहुत बढ़िया ब्रायन इयर्स ने इसके बारे में शानदार लेख लिखा, जो आपके स्विफ्ट संकलन समय को बढ़ाता है ।


2
alias grep='noglob grep'पहले zsh वाले लोगों के लिए , othewise grep काम नहीं करेगा
Jaime Agudo

16

समाधान कास्टिंग है।

मैं इस तरह के शब्दकोशों के टन का एक बड़ा सरणी था:

["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
.....

इसे संकलित करने में लगभग 40 मिनट लगे। जब तक मैंने इस तरह से शब्दकोश नहीं डाला:

["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
....

यह लगभग हर दूसरी समस्या के लिए काम करता है जिसे मैं अपने आवेदन में हार्ड कोडित डेटा प्रकारों के संबंध में चलाता था।


6
अच्छी तरह से हाँ, यह उन आशाओं का हिस्सा है जो आप संकलन समय को बेहतर बनाने के लिए करते हैं, लेकिन फिर भी वर्तमान स्विफ्ट कंपाइलर के साथ मुख्य समस्या यह है कि यह अभी भी हर एक स्विफ्ट फ़ाइल को हर बार जब आप थोड़ी सी भी संशोधन करते हैं, तब भी पुन: जमा हो जाती है।
8

4
अगर यह इतना दुखद नहीं होता तो यह मज़ेदार होगा।
टॉम एंडरसन

15

ध्यान देने वाली एक बात यह है कि स्विफ्ट टाइप इंफ़ॉर्मेशन इंजन नेस्टेड प्रकारों के साथ बहुत धीमा हो सकता है। आप इस बात के बारे में एक सामान्य विचार प्राप्त कर सकते हैं कि व्यक्तिगत संकलन इकाइयों के निर्माण लॉग को देखने में धीमेपन के कारण क्या है जो एक लंबे समय ले रहे हैं और फिर पूर्ण Xcode- स्पॉन्ड कमांड को टर्मिनल विंडो में कॉपी और पेस्ट कर रहे हैं और फिर CTRL- \ को हिट करने के लिए प्राप्त कर सकते हैं। कुछ निदान। एक पूर्ण उदाहरण के लिए http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times पर एक नज़र डालें ।


यह मेरे लिए सबसे अच्छा जवाब है (लिंक देखें)। मैं आसानी से दो अलग-अलग लाइनों को ढूंढ सकता था जो एक समस्या थी और इसे मेरी लाइनों को छोटी लाइनों में विघटित करके हल किया।
निको

यह एक बहुत ही उपयोगी उत्तर है क्योंकि यह दिखाता है कि कैसे संकलक कहाँ पागल हो गया। मेरे मामले में यह निम्नलिखित था: 'curScore [curPlayer% 2] + curScore [2 + curPlayer% 2] == 3 और& मेकर% 2 == curPlayer% 2' जैसे ही मैं 'if' से 'if' से 'लेट' गया ', इसके परिणामस्वरूप "अभिव्यक्ति उचित समय में हल करने के लिए बहुत जटिल थी; अभिव्यक्ति को अलग-अलग उप-अभिव्यक्तियों में तोड़ने पर विचार करें"
दिमित्री

यह निश्चित रूप से इस मुद्दे को हल करने का सबसे सहायक तरीका है।
रिचर्ड वेनटेबल

9

यह भी सुनिश्चित करें कि डिबग (या तो स्विफ्ट या ऑब्जेक्टिव-सी) के लिए संकलन करते समय, आप सक्रिय आर्किटेक्चर बनाने के लिए सेट करें:

यहां छवि विवरण दर्ज करें


6

चूंकि यह सब सामान बीटा में है, और चूंकि स्विफ्ट कंपाइलर (कम से कम आज के रूप में) खुला नहीं है, मुझे लगता है कि आपके प्रश्न का कोई वास्तविक उत्तर नहीं है।

सबसे पहले, ऑब्जेक्टिव-सी की तुलना स्विफ्ट कंपाइलर से करना किसी तरह क्रूर है। स्विफ्ट अभी भी बीटा में है, और मुझे यकीन है कि ऐप्पल कार्यक्षमता प्रदान करने और बग्स को ठीक करने में काम कर रहा है, बिजली की गति प्रदान करने से अधिक (आप फर्नीचर खरीदकर घर बनाना शुरू नहीं करते हैं)। मुझे लगता है कि Apple नियत समय में कंपाइलर का अनुकूलन करेगा।

यदि किसी कारण से सभी स्रोत फ़ाइलों को पूर्ण रूप से संकलित किया जाना है, तो एक विकल्प अलग मॉड्यूल / लाइब्रेरी बनाने का हो सकता है। लेकिन यह विकल्प अभी तक संभव नहीं है, क्योंकि भाषा के स्थिर होने तक स्विफ्ट पुस्तकालयों को अनुमति नहीं दे सकती है।

मेरा अनुमान है कि वे संकलक का अनुकूलन करेंगे। उसी कारण से कि हम पूर्व संकलित मॉड्यूल नहीं बना सकते हैं, यह अच्छी तरह से हो सकता है कि संकलक को खरोंच से सब कुछ संकलित करने की आवश्यकता है। लेकिन एक बार जब भाषा एक स्थिर संस्करण तक पहुंच जाती है और बायनेरिज़ का प्रारूप अब बदल नहीं रहा है, तो हम अपने पुस्तकालयों को बनाने में सक्षम होंगे, और शायद (?) कंपाइलर भी अपने काम का अनुकूलन करने में सक्षम होंगे।

हालांकि, केवल एप्पल जानता है, के लिए अनुमान लगा रहा है ...


"उसी कारण से कि हम पूर्व-संकलित मॉड्यूल नहीं बना सकते हैं, यह अच्छी तरह से हो सकता है कि संकलक को खरोंच से सब कुछ संकलित करने की आवश्यकता हो।" अच्छा अवलोकन, पहले इस तरह से इसके बारे में नहीं सोचा था।
14

1
2017 और यह अभी भी धीमा है
पेड्रो पाउलो एमोरिम

2017 Xcode 9 और नए बिल्ड सिस्टम के साथ और अभी भी धीमा है
pableiros

2018 एक्सकोड 9 के साथ, मेरे पास 50+ स्विफ्ट फ़ाइलों के साथ एक परियोजना है, अगर मैं साफ निर्माण करता हूं, तो अब 5 मिनट का निशान बीत चुका है और मेरा संकलन अभी तक नहीं हुआ है।
चेन ली योंग

5

Xcode 8 के लिए, प्रोजेक्ट सेटिंग्स पर जाएं, फिर संपादक> बिल्ड सेटिंग जोड़ें> उपयोगकर्ता-निर्धारित सेटिंग जोड़ें, और निम्नलिखित जोड़ें:

SWIFT_WHOLE_MODULE_OPTIMIZATION = YES

इस ध्वज को जोड़ने से हमारे स्वच्छ-निर्माण संकलन समय को 7 मिनट से 65 के दशक में 40KLOC स्विफ्ट प्रोजेक्ट के लिए चमत्कारिक रूप से गिरा दिया गया। यह भी पुष्टि कर सकता है कि 2 दोस्तों ने उद्यम परियोजनाओं पर समान सुधार देखा है।

मैं केवल यह मान सकता हूं कि यह Xcode 8.0 में किसी प्रकार का बग है

संपादित करें: यह कुछ लोगों के लिए Xcode 8.3 में अब काम नहीं करता है।


2
कृपया "प्रोजेक्ट सेटिंग" कहाँ है?
रानी

@Raniys Xcode में बाएँ फलक में मूल स्तर पर नीले आइकन पर क्लिक करें।
क्रिस

मुझे लग रहा है कि Xcode 8.3 (नॉन-बीटा) के रूप में यह अब मेरे मामले में काम नहीं करता है :(
क्रिस

4

दुर्भाग्य से, स्विफ्ट कंपाइलर अभी भी तेज और वृद्धिशील संकलन (एक्सकोड 6.3 बीटा के रूप में) के लिए अनुकूलित नहीं है। इस बीच आप स्विफ्ट के संकलन समय को बेहतर बनाने के लिए निम्नलिखित कुछ तकनीकों का उपयोग कर सकते हैं:

  • पुन: स्थापन प्रभाव को कम करने के लिए ऐप को चौखटे में विभाजित करें। लेकिन ध्यान रखें कि आपको अपने ऐप में चक्रीय निर्भरता से बचना चाहिए। इस विषय पर जानकारी के लिए इस पोस्ट की जाँच करें: http://bits.citrusbyte.com/improving-swift-compile-time/

  • अपने प्रोजेक्ट के उन हिस्सों के लिए स्विफ्ट का उपयोग करें जो काफी स्थिर हैं और अक्सर बदलते नहीं हैं। अन्य क्षेत्रों के लिए जहां आपको बहुत बार बदलने की आवश्यकता होती है या ऐसे क्षेत्र जिन्हें पूरा करने के लिए बहुत अधिक संकलन / रन पुनरावृत्तियों की आवश्यकता होती है (लगभग किसी भी यूआई से संबंधित सामान), बेहतर मिक्स-एंड-मैच दृष्टिकोण के साथ ऑब्जेक्टिव-सी का उपयोग करें।

  • 'Xcode के लिए इंजेक्शन' के साथ रनटाइम कोड इंजेक्शन आज़माएं

  • रोपक विधि का प्रयोग करें: http://roopc.net/posts/2014/speeding-up-swift-builds/

  • सुस्पष्ट जातियों के साथ कुछ संकेत देकर स्विफ्ट प्रकार के अनुमान इंजन को राहत दें।


4

स्विफ्ट सरणियों और शब्दकोशों का निर्माण इसके लिए एक बहुत लोकप्रिय कारण लगता है (विशेष रूप से आपके लिए जो रूबी पृष्ठभूमि से आते हैं ), अर्थात,

var a = ["a": "b",
         "c": "d",
         "e": "f",
         "g": "h",
         "i": "j",
         "k": "l",
         "m": "n",
         "o": "p",
         "q": "r",
         "s": "t",
         "u": "v",
         "x": "z"]

शायद यही कारण है कि जहां इसे ठीक करना चाहिए:

var a = NSMutableDictionary()
a["a"] = "b"
a["c"] = "d"
... and so on

4

डिबग और परीक्षण के लिए, संकलित समय को 20 मिनट से कम से कम 2 मिनट तक काटने के लिए निम्नलिखित सेटिंग्स का उपयोग करना सुनिश्चित करें,

  1. प्रोजेक्ट बिल्ड सेटिंग्स में, "ऑप्टिमाइज़ेशन" टर्न डीबग को "फास्टेस्ट [-ओ 3]" या उससे ऊपर की खोज करें।
  2. सक्रिय आर्किटेक्चर के लिए बिल्ड सेट करें: हाँ
  3. डिबग सूचना प्रारूप: DWARF
  4. संपूर्ण मॉड्यूल अनुकूलन: नहीं

मैं परियोजना के लिए केवल महसूस करने के लिए अनगिनत घंटे बर्बाद कर रहा था मुझे महसूस करना था कि मुझे थोड़ा बदलाव करना है और इसे परीक्षण करने के लिए पूरे 30 मिनट तक इंतजार करना होगा। ये सेटिंग्स हैं जो मेरे लिए काम करती हैं। (मैं अभी भी सेटिंग्स के साथ प्रयोग कर रहा हूं)

लेकिन, सुनिश्चित करें कि आप कम से कम "DWARF with dSYM" (यदि आप अपने एप्लिकेशन की निगरानी करना चाहते हैं) सेट करें और iTunes Connect से कनेक्ट करने के लिए रिलीज़ / आर्काइविंग के लिए "NO" पर एक्टिव आर्किटेक्चर बनाएँ (मुझे याद है कि यहां कुछ घंटे भी बर्बाद हो रहे हैं)।


4
मैं गलत हो सकता हूं, लेकिन वास्तव में बिल्ड समय में वृद्धि के अनुकूलन के स्तर को नहीं बढ़ाएगा? अनुकूलन स्तर रनटाइम प्रदर्शन में सुधार करेगा।
माइकल झरना

1
Set Build for Active Architecture: YESमुझे संकलन समय में लगभग 45% की कमी दी। बहुत धन्यवाद।
जीन ले मोइगन

4

कंपाइलर प्रकारों की जाँच और जाँच में बहुत समय व्यतीत करता है। इसलिए टाइप एनोटेशन जोड़ने से कंपाइलर को काफी मदद मिलती है।

यदि आपके पास बहुत सारे जंजीरदार फ़ंक्शन कॉल हैं

let sum = [1,2,3].map({String($0)}).flatMap({Float($0)}).reduce(0, combine: +)

फिर संकलक को यह पता लगाने में थोड़ा समय लगता है कि किस प्रकार का sumहोना चाहिए। प्रकार जोड़ने से मदद मिलती है। जो भी मदद करता है वह आंतरायिक चरणों को अलग-अलग चर में खींच रहा है।

let numbers: [Int] = [1,2,3]
let strings: [String] = sum.map({String($0)})
let floats: [Float] = strings.flatMap({Float($0)})
let sum: Float = floats.reduce(0, combine: +)

विशेष रूप से संख्यात्मक प्रकारों के लिए CGFloat, Intयह बहुत मदद कर सकता है। एक शाब्दिक संख्या की तरह2 कई अलग-अलग संख्यात्मक प्रकारों का प्रतिनिधित्व कर सकती है। इसलिए संकलक को उस संदर्भ से जानने की जरूरत है जो वह है।

ऐसे कार्य जिन्हें देखने में बहुत समय लगता है, +उनसे भी बचना चाहिए। +कई सरणियों का उपयोग करना कई सरणियों धीमा है क्योंकि संकलक को यह पता लगाने की आवश्यकता है कि +प्रत्येक के लिए किस कार्यान्वयन को बुलाया जाना चाहिए +। इसलिए यदि संभव हो तो इसके var a: [Foo]साथ एक का उपयोग करें append()

आप यह पता लगाने के लिए एक चेतावनी जोड़ सकते हैं कि कौन से कार्य Xcode में संकलित करने के लिए धीमा हैं

में सेटिंग्स बिल्ड के लिए अपने लक्षित खोज के लिए अन्य स्विफ्ट झंडे और ऐड

-Xfrontend -warn-long-function-bodies=100

संकलन करने के लिए 100 ms से अधिक समय लेने वाले प्रत्येक फ़ंक्शन के लिए चेतावनी देना।


4

उद्देश्य-सी और स्विफ्ट कोड को मिलाने वाली परियोजनाओं के लिए, हम इसमें सेट कर सकते -enable-bridging-pchहैं Other Swift Flags। इसके साथ, ब्रिजिंग हेडर को केवल एक बार पार्स किया जाता है, और परिणाम (एक अस्थायी "पूर्वनिर्धारित हेडर" या "पीसीएच" फ़ाइल) को कैश किया जाता है और लक्ष्य में सभी स्विफ्ट फ़ाइलों में पुन: उपयोग किया जाता है। Apple ने दावा किया कि यह निर्माण समय 30% तक घट जाता है। संदर्भ लिंक:

नोट: यह स्विफ्ट 3.1 और इसके बाद के संस्करण के लिए काम करता है।


2

मेरे मैक को रिबूट करने से इस मुद्दे पर आश्चर्य हुआ। मैं रिबूट करके सिर्फ 15 मिनट के बिल्ड से 30 सेकंड के बिल्ड पर गया।


1

नई Xcode 6.3 में स्विफ्ट संकलन समय में सुधार किया गया था

संकलक सुधार

स्विफ्ट 1.2 संकलक को अधिक स्थिर होने और हर तरह से प्रदर्शन में सुधार करने के लिए इंजीनियर किया गया था। ये बदलाव Xcode में स्विफ्ट के साथ काम करने के दौरान एक बेहतर अनुभव प्रदान करते हैं। सबसे अधिक दिखाई देने वाले कुछ सुधारों में शामिल हैं:

वृद्धिशील बनाता है

स्रोत फ़ाइलें जो अब नहीं बदली हैं, उन्हें डिफ़ॉल्ट रूप से फिर से संकलित नहीं किया जाएगा, जो कि अधिकांश सामान्य मामलों के निर्माण के समय में काफी सुधार करेगा। आपके कोड में बड़े संरचनात्मक परिवर्तन के लिए अभी भी कई फाइलों को फिर से बनाने की आवश्यकता हो सकती है।

तेज़ निष्पादन

डीबग बिल्ड बायनेरिज़ का निर्माण करता है जो बहुत तेज़ी से चलता है, और नई अनुकूलन बेहतर रिलीज़ बिल्ड प्रदर्शन प्रदान करते हैं।

बेहतर कंपाइलर डायग्नोस्टिक्स

नई फिक्स-के साथ स्पष्ट त्रुटि और चेतावनी संदेश, उचित स्विफ्ट 1.2 कोड लिखना आसान बनाता है।

स्थिरता में सुधार

सबसे आम संकलक क्रैश तय किए गए हैं। आपको Xcode संपादक के भीतर कम SourceKit चेतावनी भी देखनी चाहिए।


0

यहां एक और मामला है जो प्रकार की मंदी के साथ बड़े पैमाने पर मंदी का कारण बन सकता है। सहते हुए संचालक

लाइनों को बदलना जैसे:

abs(some_optional_variable ?? 0)

सेवा

abs((some_optional_variable ?? 0) as VARIABLE_TYPE)

70 से 13 के दशक तक मेरे संकलन समय को लाने में मदद की


0

मेरे लिए Xcode 6.3.1 में कुछ भी काम नहीं किया गया - जब मैंने 100 स्विफ्ट फ़ाइलों को जोड़ दिया तो Xcode बेतरतीब ढंग से बिल्ड और / या इंडेक्सिंग पर लटका दिया गया। मैंने बिना किसी सफलता के एक मॉड्यूलर विकल्प की कोशिश की है।

स्थापित करना और Xcode 6.4 बीटा का उपयोग करना वास्तव में मेरे लिए काम करता है।


0

यह मेरे लिए जादू की तरह काम कर रहा है - स्पीड अप स्विफ्ट संकलन । इसने संकलन समय को 10 मिनट से घटाकर 3 मिनट कर दिया।

इसे कहते हैं आप चालू करना चाहिए Whole Module Optimization, जबकि जोड़ने -Ononeमें Other Swift Flags

मैं उपयोग कर रहा हूँ Swift 3पर Xcode 8.3/Xcode 8.2


0

पूर्णांक शाब्दिक और फ्लोट शाब्दिक को एक अभिव्यक्ति में मिलाने से भी लंबे संकलन का समय मिलता है।

1.0 + (1.0 + (1  * (1.0 + 1.0))) // 3429ms

1.0 + (1.0 + (1.0  * (1.0 + 1.0))) // 5ms

कई 1000 + एमएस संकलन-समय के भाव 10 ~ 100ms कम हो जाते हैं जब मैं एक .0पूर्णांक शाब्दिक डाल देता हूं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.