बिल्ड परफ़ॉर्मेंस का विश्लेषण

समस्या की शिकायत करें स्रोत देखें

Bazel जटिल है और वह बिल्ड के दौरान कई अलग-अलग काम करता है. इनमें से कुछ चीज़ों से बिल्ड की परफ़ॉर्मेंस पर असर पड़ सकता है. इस पेज पर, Bazel के कुछ कॉन्सेप्ट को समझने की कोशिश की गई है. इससे, यह पता चलेगा कि परफ़ॉर्मेंस पर इनका क्या असर होगा. हालांकि, हमने इसके बारे में कुछ उदाहरण दिए हैं. इसमें हमने बताया है कि मेट्रिक एक्सट्रैक्ट करके, बिल्ड परफ़ॉर्मेंस से जुड़ी समस्याओं का कैसे पता लगाएं और उन्हें कैसे ठीक करें. हमें उम्मीद है कि इससे बिल्ड परफ़ॉर्मेंस रिग्रेशन की जांच करते समय इन सिद्धांतों को लागू किया जा सकेगा.

क्लीन और इंक्रीमेंटल बिल्ड

क्लीन बिल्ड वह होता है जिसमें शुरुआत से सब कुछ बनाया जाता है. वहीं, इंक्रीमेंटल बिल्ड, पहले से पूरे हो चुके कुछ काम का फिर से इस्तेमाल करता है.

हमारा सुझाव है कि क्लीन और इंक्रीमेंटल बिल्ड को अलग-अलग देखें. खास तौर पर, जब आप ऐसी मेट्रिक इकट्ठा / एग्रीगेट कर रहे हों जो Bazel की कैश मेमोरी की स्थिति पर निर्भर करती हैं (उदाहरण के लिए, अनुरोध के साइज़ की मेट्रिक बनाएं ). ये दो अलग-अलग उपयोगकर्ता अनुभवों को भी दिखाते हैं. नए सिरे से एक क्लीन बिल्ड शुरू करने (जिसमें कोल्ड कैश की वजह से ज़्यादा समय लगता है) की तुलना में, इंक्रीमेंटल (बढ़ने वाले) बिल्ड कई बार होते हैं, जब डेवलपर कोड को बार-बार दोहराते हैं (आम तौर पर, यह ज़्यादा तेज़ होता है, क्योंकि कैश मेमोरी पहले से ही गर्म होती है).

बिल्ड की कैटगरी तय करने के लिए, बीईपी में CumulativeMetrics.num_analyses फ़ील्ड का इस्तेमाल किया जा सकता है. अगर num_analyses <= 1, तो यह एक क्लीन बिल्ड है. ऐसा न होने पर, हम इसे बड़े पैमाने पर इंक्रीमेंटल बिल्ड के तौर पर तय कर सकते हैं - हो सकता है कि उपयोगकर्ता ने अलग-अलग फ़्लैग या अलग-अलग टारगेट पर स्विच किया हो, जिसकी वजह से यह अच्छी तरह से क्लीन होता हो. बढ़ोतरी की किसी भी ज़्यादा सटीक परिभाषा को एक अनुमान के तौर पर देखना होगा. उदाहरण के लिए, लोड किए गए पैकेज की संख्या (PackageMetrics.packages_loaded) पर ध्यान देना.

परफ़ॉर्मेंस बेहतर बनाने के लिए, प्रॉक्सी के तौर पर तय करने वाले बिल्ड मेट्रिक

कुछ मेट्रिक (उदाहरण के लिए, किसी रिमोट क्लस्टर पर Bazel का सीपीयू समय या सूची में लगने वाला समय) जैसी कुछ मेट्रिक की तय नहीं होती हैं. इस वजह से, बिल्ड परफ़ॉर्मेंस को मापना मुश्किल हो सकता है. इसलिए, Bazel के किए गए काम के लिए, प्रॉक्सी के तौर पर डिटरमिनिस्टिक मेट्रिक का इस्तेमाल करना फ़ायदेमंद हो सकता है, जिससे उसकी परफ़ॉर्मेंस पर असर पड़ता है.

बिल्ड के अनुरोध की संख्या का असर बिल्ड की परफ़ॉर्मेंस पर पड़ सकता है. बड़े बिल्ड से बिल्ड ग्राफ़ का विश्लेषण करने और उसे बनाने में ज़्यादा काम करना पड़ सकता है. बिल्ड के होने की ऑर्गैनिक ग्रोथ, स्वाभाविक तौर पर डेवलपमेंट के साथ होती है. इसकी वजह यह है कि इसमें ज़्यादा डिपेंडेंसी जोड़ी या बनाई जाती है. इस वजह से, काम करना मुश्किल हो जाता है और इसे बनाना महंगा हो जाता है.

हम इस समस्या को बिल्ड के अलग-अलग चरणों में बांट सकते हैं. साथ ही, हर चरण में पूरे किए गए काम के लिए, इन मेट्रिक का इस्तेमाल प्रॉक्सी मेट्रिक के तौर पर कर सकते हैं:

  1. PackageMetrics.packages_loaded: लोड किए गए पैकेज की संख्या. यहां दिया गया रिग्रेशन, लोड होने वाले फ़ेज़ में BUILD फ़ाइल को पढ़ने और पार्स करने के लिए ज़्यादा काम को दिखाता है.

    • ऐसा अक्सर डिपेंडेंसी जोड़ने और उनके ट्रांज़िशन के बंद होने के समय को लोड करने की वजह से होता है.
    • query / cquery का इस्तेमाल करके जानें कि नई डिपेंडेंसी कहां जोड़ी गई हैं.
  2. TargetMetrics.targets_configured: यह बिल्ड में कॉन्फ़िगर किए गए टारगेट और लक्ष्यों की संख्या दिखाता है. रिग्रेशन, कॉन्फ़िगर किए गए टारगेट ग्राफ़ को बनाने और ट्रैवर्स करने में ज़्यादा काम करता है.

    • ऐसा अक्सर डिपेंडेंसी के जुड़ने की वजह से और उनके ट्रांज़िटिव क्लोज़र का ग्राफ़ बनाने की वजह से होता है.
    • cquery का इस्तेमाल करके पता लगाएं कि नई डिपेंडेंसी कहां जोड़ी गई हैं.
  3. ActionSummary.actions_created: इससे बिल्ड में बनाए गए ऐक्शन का पता चलता है और रिग्रेशन से, ऐक्शन ग्राफ़ को बनाने में ज़्यादा काम के बारे में पता चलता है. ध्यान दें कि इसमें इस्तेमाल न की गई ऐसी कार्रवाइयां भी शामिल हैं जो शायद पूरी न की गई हों.

    • रिग्रेशन को डीबग करने के लिए, क्वेरी का इस्तेमाल करें. हमारा सुझाव है कि --skyframe_state के साथ ज़्यादा ड्रिल-डाउन करने से पहले, --output=summary से शुरुआत करें.
  4. ActionSummary.actions_executed: की गई कार्रवाइयों की संख्या, रिग्रेशन से सीधे तौर पर पता चलता है कि इन कार्रवाइयों पर कितना ज़्यादा काम किया गया है.

    • BEP, कार्रवाई के आंकड़े ActionData लिखता है. इसमें सबसे ज़्यादा लागू की गई कार्रवाई के टाइप दिखते हैं. डिफ़ॉल्ट रूप से, यह मुख्य 20 तरह की कार्रवाई इकट्ठा करता है. हालांकि, कोई भी कार्रवाई की गई हर तरह की कार्रवाई के लिए यह डेटा इकट्ठा करने के लिए, --experimental_record_metrics_for_all_mnemonics को पास किया जा सकता है.
    • इससे आपको यह पता लगाने में मदद मिलेगी कि किस तरह की कार्रवाइयां की गई थीं (इसके अलावा).
  5. BuildGraphSummary.outputArtifactCount: की गई कार्रवाइयों से बने आर्टफ़ैक्ट की संख्या.

    • अगर लागू की गई कार्रवाइयों की संख्या में बढ़ोतरी नहीं हुई है, तो हो सकता है कि नियम लागू करने का तरीका बदल गया हो.

इन सभी मेट्रिक पर, लोकल कैश मेमोरी की स्थिति का असर पड़ता है. इसलिए, आपको यह पक्का करना चाहिए कि जिन बिल्ड से ये मेट्रिक ली जाती हैं वे क्लीन बिल्ड हों.

हमने देखा है कि इनमें से किसी भी मेट्रिक में रिग्रेशन के साथ-साथ वॉल टाइम, सीपीयू टाइम, और मेमोरी के इस्तेमाल में रिग्रेशन भी हो सकते हैं.

स्थानीय संसाधनों का इस्तेमाल

Bazel आपकी लोकल मशीन पर कई तरह के संसाधनों का इस्तेमाल करता है. इसमें बिल्ड ग्राफ़ का विश्लेषण करने, एक्ज़ीक्यूशन को चलाने, और लोकल ऐक्शन करने के लिए, दोनों का इस्तेमाल होता है. इससे बिल्ड के साथ-साथ दूसरे टास्क के लिए, आपकी मशीन की परफ़ॉर्मेंस / उपलब्धता पर असर पड़ सकता है.

बिताया गया समय

शायद उन मेट्रिक पर सबसे ज़्यादा शोर हो सकता है जिन्हें बनाने में बहुत ज़्यादा अंतर दिख सकता है. खास तौर पर, समय में यह मेट्रिक होती है. खास तौर पर, समय, सीपीयू के समय, और सिस्टम के समय में. इन मेट्रिक के लिए मानदंड पाने के लिए, bazel-bench का इस्तेमाल किया जा सकता है. साथ ही, अपनी ज़रूरत के मुताबिक --runs की मदद से, मेज़रमेंट के आंकड़ों का महत्व बढ़ाया जा सकता है.

  • वॉल टाइम असल दुनिया में बीता हुआ समय है.

    • अगर सिर्फ़ वॉल टाइम रिग्रेशन होता है, तो हमारा सुझाव है कि आप JSON ट्रेस प्रोफ़ाइल इकट्ठा करें और अंतर का पता लगाएं. ऐसा न करने पर, अन्य रीग्रेस मेट्रिक की जांच करना ज़्यादा बेहतर होगा, क्योंकि इनसे वॉल टाइम पर असर पड़ सकता है.
  • सीपीयू समय, वह समय है जो उपयोगकर्ता कोड को लागू करने में सीपीयू की मदद करता है.

    • अगर दो प्रोजेक्ट के लिए सीपीयू का समय कम होता है, तो हमारा सुझाव है कि आप Starlark सीपीयू प्रोफ़ाइल इकट्ठा करें. आपको विश्लेषण के चरण तक बिल्ड को सीमित करने के लिए, --nobuild का भी इस्तेमाल करना चाहिए. इसकी वजह यह है कि सीपीयू का ज़्यादातर काम वहीं से किया जाता है.
  • सिस्टम का समय, वह समय होता है जो CPU ने कर्नेल में बिताया है.

    • अगर सिस्टम का समय फिर से हासिल होता है, तो यह ज़्यादातर I/O से जुड़ा होता है, जब Bazel आपके फ़ाइल सिस्टम की फ़ाइलों को पढ़ता है.

पूरे सिस्टम के लिए लोड प्रोफ़ाइलिंग

Bazel 6.0 में पेश किए गए --experimental_collect_load_average_in_profiler फ़्लैग का इस्तेमाल करके, JSON ट्रेस प्रोफ़ाइलर, कॉल शुरू करने के दौरान सिस्टम लोड का औसत इकट्ठा करता है.

वह प्रोफ़ाइल जिसमें सिस्टम लोड औसत शामिल है

पहला डायग्राम. वह प्रोफ़ाइल जिसमें सिस्टम लोड औसत शामिल है.

Bazel के शुरू करने के दौरान ज़्यादा लोड इस बात का संकेत हो सकता है कि Bazel आपकी मशीन पर एक साथ बहुत सारी स्थानीय कार्रवाइयां शेड्यूल करता है. आपको --local_cpu_resources और --local_ram_resources में बदलाव करने के बारे में सोचना पड़ सकता है, खास तौर पर कंटेनर एनवायरमेंट में (कम से कम #16512 के मर्ज होने तक).

Bazel मेमोरी के इस्तेमाल पर नज़र रखना

Bazel के लिए मेमोरी के इस्तेमाल की जानकारी पाने के दो मुख्य सोर्स हैं, Bazel info और BEP.

  • bazel info used-heap-size-after-gc: System.gc() पर कॉल करने के बाद, बाइट में इस्तेमाल की गई मेमोरी.

    • बेज़ेल बेंच इस मेट्रिक के लिए भी मानदंड उपलब्ध कराता है.
    • इसके अलावा, इनमें peak-heap-size, max-heap-size, used-heap-size, और committed-heap-size भी हैं (दस्तावेज़ देखें), लेकिन ये कम काम के हैं.
  • BEP MemoryMetrics.peak_post_gc_heap_size: GC के बाद, बाइट में JVM हीप के सबसे ऊंचे साइज़ का साइज़ (यह सेटिंग ज़रूरी है --memory_profile, जो पूरे GC को लागू करने की कोशिश करती है).

आम तौर पर, मेमोरी के इस्तेमाल में रिग्रेशन, अनुरोध साइज़ की मेट्रिक बनाने में रिग्रेशन की वजह से होता है. ऐसा अक्सर डिपेंडेंसी के जुड़ने या नियम लागू करने में बदलाव की वजह से होता है.

अगर आपको Bazel की मेमोरी का इस्तेमाल ज़्यादा बारीकी से करना है, तो हमारा सुझाव है कि आप नियमों के लिए, पहले से मौजूद मेमोरी प्रोफ़ाइलर का इस्तेमाल करें.

लगातार काम करने वाले कर्मचारियों की मेमोरी की प्रोफ़ाइल बनाना

नियमित तौर पर काम करने वाले वर्कर, बिल्ड को बहुत तेज़ी से बढ़ाने में मदद कर सकते हैं (खास तौर पर, इंटरप्रेटेड लैंग्वेज के लिए), उनकी मेमोरी फ़ुटप्रिंट से जुड़ी समस्याओं का सामना करना पड़ सकता है. Bazel अपने वर्कर से जुड़ी मेट्रिक इकट्ठा करता है. खास तौर पर, WorkerMetrics.WorkerStats.worker_memory_in_kb फ़ील्ड से यह पता चलता है कि कर्मचारी कितनी मेमोरी इस्तेमाल कर रहे हैं (Memonic के आधार पर).

JSON ट्रेस प्रोफ़ाइल, कॉल शुरू करने के दौरान वर्कर की मेमोरी में मौजूद मेमोरी को भी इकट्ठा करता है. ऐसा करने के लिए, --experimental_collect_system_network_usage फ़्लैग (Bzel 6.0 में नया) को पास किया जाता है.

वह प्रोफ़ाइल जिसमें वर्कर मेमोरी का इस्तेमाल शामिल है

दूसरी इमेज. वह प्रोफ़ाइल जिसमें वर्कर मेमोरी का इस्तेमाल शामिल है.

--worker_max_instances (डिफ़ॉल्ट 4) की वैल्यू को कम करने से, काम करने वाले स्थायी कर्मचारियों के लिए इस्तेमाल की जाने वाली मेमोरी को कम करने में मदद मिल सकती है. हम Bazel के संसाधन मैनेजर और शेड्यूलर को बेहतर बनाने के लिए लगातार काम कर रहे हैं, ताकि आने वाले समय में इस तरह की बेहतर ट्यूनिंग की ज़रूरत कम पड़े.

रिमोट बिल्ड के लिए नेटवर्क ट्रैफ़िक की निगरानी करना

रिमोट एक्ज़ीक्यूशन के दौरान, Bazel उन आर्टफ़ैक्ट को डाउनलोड करता है जो कार्रवाइयों को पूरा करके बनाए गए थे. इससे आपके नेटवर्क बैंडविथ से, बिल्ड की परफ़ॉर्मेंस पर असर पड़ सकता है.

अगर अपने बिल्ड के लिए रिमोट एक्ज़ीक्यूशन का इस्तेमाल किया जा रहा है, तो हो सकता है कि आप शुरू करने के दौरान बीईपी के NetworkMetrics.SystemNetworkStats प्रोटो का इस्तेमाल करके, नेटवर्क ट्रैफ़िक पर नज़र रखना चाहें (--experimental_collect_system_network_usage को पास करना ज़रूरी है).

इसके अलावा, JSON ट्रेस प्रोफ़ाइल की मदद से बिल्ड के दौरान --experimental_collect_system_network_usage फ़्लैग (Bzel 6.0 में नया) को पास करके, पूरे सिस्टम के नेटवर्क के इस्तेमाल की जानकारी देखी जा सकती है.

वह प्रोफ़ाइल जिसमें पूरे सिस्टम पर नेटवर्क के इस्तेमाल की जानकारी शामिल है

तीसरी इमेज. वह प्रोफ़ाइल जिसमें पूरे सिस्टम पर नेटवर्क के इस्तेमाल की जानकारी शामिल है.

रिमोट एक्ज़ीक्यूशन का इस्तेमाल करते समय, नेटवर्क का बहुत ज़्यादा इस्तेमाल होने का मतलब है कि यह आपके बिल्ड में रुकावट डाल सकता है. अगर आपने पहले से इसका इस्तेमाल नहीं किया है, तो --remote_download_minimal पास करके, बाइट के बिना बिल्ड चालू करें. इससे इंटरमीडिएट आर्टफ़ैक्ट डाउनलोड होने से रोका जा सकेगा और आपके बिल्ड की स्पीड तेज़ हो जाएगी.

दूसरा विकल्प यह है कि डाउनलोड बैंडविड्थ को सेव करने के लिए लोकल डिस्क कैश को कॉन्फ़िगर करें.