Bazel का इस्तेमाल करना मुश्किल है. यह बिल्ड के दौरान कई अलग-अलग काम करता है. इनमें से कुछ कामों का असर बिल्ड की परफ़ॉर्मेंस पर पड़ सकता है. इस पेज पर, Bazel के कुछ कॉन्सेप्ट को मैप करने की कोशिश की गई है, ताकि यह पता लगाया जा सके कि इन कॉन्सेप्ट का असर बिल्ड की परफ़ॉर्मेंस पर कैसे पड़ता है. हमने मेट्रिक निकालने के ज़रिए, बिल्ड की परफ़ॉर्मेंस से जुड़ी समस्याओं का पता लगाने और उन्हें ठीक करने के तरीके के कुछ उदाहरण दिए हैं. हालांकि, इनमें पूरी जानकारी नहीं दी गई है. हमें उम्मीद है कि इसके साथ ही, बिल्ड परफ़ॉर्मेंस रिग्रेशन की जांच करते समय इन सिद्धांतों को लागू किया जा सकेगा.
क्लीन बनाम इंक्रीमेंटल बिल्ड
क्लीन बिल्ड में, सब कुछ नए सिरे से बनाया जाता है. वहीं, इंक्रीमेंटल बिल्ड में, पहले से किए गए कुछ काम का फिर से इस्तेमाल किया जाता है.
हमारा सुझाव है कि क्लीन और इंक्रीमेंटल बिल्ड को अलग-अलग देखें. ऐसा तब ज़रूर करें, जब आप ऐसी मेट्रिक इकट्ठा या एग्रीगेट कर रहे हों जो Bazel के कैश मेमोरी की स्थिति पर निर्भर करती हैं. उदाहरण के लिए, बिल्ड रिक्वेस्ट के साइज़ की मेट्रिक. ये मेट्रिक, उपयोगकर्ताओं को दो अलग-अलग अनुभव भी देती हैं. शुरुआत से क्लीन बिल्ड शुरू करने की तुलना में (जिसमें कोल्ड कैश की वजह से ज़्यादा समय लगता है), इंक्रीमेंटल बिल्ड ज़्यादा बार होते हैं, क्योंकि डेवलपर कोड को दोहराते हैं. आम तौर पर, यह ज़्यादा तेज़ी से होता है, क्योंकि कैश मेमोरी पहले से ही गर्म होती है.
बीईपी में CumulativeMetrics.num_analyses
फ़ील्ड का इस्तेमाल करके, बिल्ड को अलग-अलग कैटगरी में बांटा जा सकता है. अगर num_analyses <= 1
है, तो यह क्लीन बिल्ड है. अगर ऐसा नहीं है, तो हम इसे बड़े पैमाने पर इंक्रीमेंटल बिल्ड के तौर पर कैटगरी में रख सकते हैं. ऐसा इसलिए, क्योंकि हो सकता है कि उपयोगकर्ता ने अलग-अलग फ़्लैग या अलग-अलग टारगेट पर स्विच किया हो, जिसकी वजह से क्लीन बिल्ड असरदार तरीके से हुआ हो. इंक्रीमेंटलिटी की ज़्यादा सटीक परिभाषा, हेयुरिस्टिक्स के तौर पर दी जा सकती है. उदाहरण के लिए, लोड किए गए पैकेज की संख्या (PackageMetrics.packages_loaded
) देखना.
बिल्ड की परफ़ॉर्मेंस के प्रॉक्सी के तौर पर, डिटरमिनिस्टिक बिल्ड मेट्रिक
कुछ मेट्रिक की इन मेट्रिक की वजह से, बिल्ड की परफ़ॉर्मेंस को मेज़र करना मुश्किल हो सकता है. ये मेट्रिक अलग-अलग नहीं होती हैं. उदाहरण के लिए, Baze का सीपीयू टाइम या रिमोट क्लस्टर पर सूची में लगने वाला समय. इसलिए, यह फ़ायदेमंद हो सकता है कि आप तय मेट्रिक का इस्तेमाल, Bazel के किए गए काम की संख्या के लिए प्रॉक्सी के तौर पर करें. इससे, Bazel की परफ़ॉर्मेंस पर असर पड़ता है.
बिल्ड के अनुरोध के साइज़ का असर, बिल्ड की परफ़ॉर्मेंस पर पड़ सकता है. बड़े बिल्ड का मतलब है कि बिल्ड ग्राफ़ का विश्लेषण करने और उन्हें बनाने में ज़्यादा काम करना पड़ सकता है. डेवलपमेंट के साथ-साथ, बिल्ड का ऑर्गैनिक तरीके से साइज़ अपने-आप बढ़ता जाता है. ऐसा इसलिए होता है, क्योंकि ज़्यादा डिपेंडेंसी जोड़ी जाती हैं या बनाई जाती हैं. इससे बिल्ड की जटिलता बढ़ती है और उसे बनाने में ज़्यादा खर्च आता है.
हम इस समस्या को बिल्ड के अलग-अलग चरणों में बांट सकते हैं और हर चरण में किए जाने वाले काम के लिए इन मेट्रिक का इस्तेमाल प्रॉक्सी मेट्रिक के रूप में कर सकते हैं:
PackageMetrics.packages_loaded
: सफलतापूर्वक लोड हुए पैकेज की संख्या. यहां रेग्रेसन का मतलब है कि लोडिंग के दौरान, हर अतिरिक्त BUILD फ़ाइल को पढ़ने और पार्स करने के लिए ज़्यादा काम करना पड़ता है.TargetMetrics.targets_configured
: इससे बिल्ड में कॉन्फ़िगर किए गए टारगेट और एस्पेक्ट की संख्या का पता चलता है. रिग्रेशन से, कॉन्फ़िगर किए गए टारगेट ग्राफ़ को बनाने और उसे ट्रैक करने की प्रोसेस पर ज़्यादा काम होता है.- ऐसा अक्सर डिपेंडेंसी जोड़ने और उनके ट्रांज़िशन क्लोज़र का ग्राफ़ बनाने की वजह से होता है.
- cquery का इस्तेमाल करके पता लगाएं कि नई डिपेंडेंसी कहां जोड़ी गई हैं.
ActionSummary.actions_created
: यह बिल्ड में बनाई गई कार्रवाइयों को दिखाता है. साथ ही, रिग्रेशन से पता चलता है कि ऐक्शन ग्राफ़ बनाने में ज़्यादा काम किया गया है. ध्यान दें कि इसमें ऐसी कार्रवाइयां भी शामिल हैं जिन्हें इस्तेमाल नहीं किया गया है और हो सकता है कि उन्हें लागू न किया गया हो.- रिग्रेशन को डीबग करने के लिए aquery का इस्तेमाल करें. हमारा सुझाव है कि
--skyframe_state
के साथ आगे ड्रिल-डाउन करने से पहले--output=summary
से शुरुआत करें.
- रिग्रेशन को डीबग करने के लिए aquery का इस्तेमाल करें. हमारा सुझाव है कि
ActionSummary.actions_executed
: लागू की गई कार्रवाइयों की संख्या, रिग्रेशन सीधे तौर पर इन कार्रवाइयों को लागू करने के ज़्यादा काम को दिखाता है.- BEP, ऐक्शन के आंकड़े लिखता है
ActionData
. इससे, सबसे ज़्यादा इस्तेमाल किए गए ऐक्शन टाइप के बारे में पता चलता है. डिफ़ॉल्ट रूप से, यह टॉप 20 ऐक्शन टाइप इकट्ठा करता है. हालांकि,--experimental_record_metrics_for_all_mnemonics
को पास करके, यह डेटा उन सभी ऐक्शन टाइप के लिए इकट्ठा किया जा सकता है जिन्हें लागू किया गया था. - इससे आपको यह पता चलेगा कि अतिरिक्त तौर पर किस तरह की कार्रवाइयां की गईं.
- BEP, ऐक्शन के आंकड़े लिखता है
BuildGraphSummary.outputArtifactCount
: एक्ज़ीक्यूट की गई कार्रवाइयों से बनाए गए आर्टफ़ैक्ट की संख्या.- अगर लागू की गई कार्रवाइयों की संख्या नहीं बढ़ी है, तो हो सकता है कि नियम लागू करने का तरीका बदला गया हो.
ये सभी मेट्रिक, लोकल कैश मेमोरी की स्थिति से प्रभावित होती हैं. इसलिए, आपको यह पक्का करना होगा कि आप जिन बिल्ड से इन मेट्रिक को एक्सट्रैक्ट करते हैं वे साफ़ बिल्ड हों.
हमने पाया है कि इनमें से किसी भी मेट्रिक में गिरावट आने पर, वॉल टाइम, सीपीयू टाइम, और मेमोरी के इस्तेमाल में भी गिरावट आ सकती है.
स्थानीय संसाधनों का इस्तेमाल
Bazel, आपकी लोकल मशीन पर कई तरह के संसाधनों का इस्तेमाल करता है. इनमें, बग़ल ग्राफ़ का विश्लेषण करने, उसे चलाने, और लोकल ऐक्शन चलाने के लिए इस्तेमाल होने वाले संसाधन शामिल हैं. इससे, बग़ल करने और अन्य टास्क को पूरा करने में आपकी मशीन की परफ़ॉर्मेंस / उपलब्धता पर असर पड़ सकता है.
बिताया गया समय
शायद समय, ऐसी मेट्रिक है जो ग़ैर-ज़रूरी डेटा से सबसे ज़्यादा प्रभावित होती है. साथ ही, यह हर बिल्ड के हिसाब से काफ़ी अलग-अलग हो सकती है. खास तौर पर, वॉल टाइम, सीपीयू टाइम, और सिस्टम टाइम. इन मेट्रिक के लिए बेंचमार्क पाने के लिए, bazel-bench का इस्तेमाल किया जा सकता है. साथ ही, ज़रूरत के मुताबिक --runs
की संख्या से, मेज़रमेंट के आंकड़ों का महत्व बढ़ाया जा सकता है.
वॉल टाइम, असल दुनिया में बीता हुआ समय होता है.
- अगर सिर्फ़ दीवार में लगने वाला समय रिग्रेस हुआ है, तो हमारा सुझाव है कि आप JSON ट्रेस प्रोफ़ाइल इकट्ठा करें और अंतर ढूंढने के लिए ऐसा करें. अगर ऐसा नहीं है, तो बेहतर होगा कि आप उन मेट्रिक की जांच करें जिनकी परफ़ॉर्मेंस में गिरावट आई है. ऐसा इसलिए, क्योंकि इनसे वेबसाइट पर बिताए गए समय पर असर पड़ सकता है.
सीपीयू का समय वह समय होता है जो सीपीयू, उपयोगकर्ता कोड को लागू करने में बिताता है.
- अगर प्रोजेक्ट के दो कमिट के बीच सीपीयू का समय कम हो जाता है, तो हमारा सुझाव है कि आप Starlark सीपीयू प्रोफ़ाइल इकट्ठा करें. आपको
--nobuild
का इस्तेमाल करके, बिल्ड को विश्लेषण के फ़ेज़ तक सीमित रखना चाहिए, क्योंकि सीपीयू का ज़्यादातर काम यहीं होता है.
- अगर प्रोजेक्ट के दो कमिट के बीच सीपीयू का समय कम हो जाता है, तो हमारा सुझाव है कि आप Starlark सीपीयू प्रोफ़ाइल इकट्ठा करें. आपको
सिस्टम टाइम, सीपीयू के कर्नेल में बिताया गया समय होता है.
- अगर सिस्टम का समय, रिग्रेशन करता है, तो ज़्यादातर मामलों में यह I/O से जुड़ा होता है. ऐसा तब होता है, जब Baze आपके फ़ाइल सिस्टम से फ़ाइलें पढ़ता है.
सिस्टम-वाइड लोड प्रोफ़ाइलिंग
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()
को कॉल करने के बाद, इस्तेमाल की गई मेमोरी का साइज़, बाइट में.- Bazel bench, इस मेट्रिक के लिए भी बेंचमार्क उपलब्ध कराता है.
- इसके अलावा,
peak-heap-size
,max-heap-size
,used-heap-size
औरcommitted-heap-size
(दस्तावेज़ देखें) भी हैं, लेकिन ये उतने काम के नहीं हैं.
BEP के
MemoryMetrics.peak_post_gc_heap_size
: जीसी के बाद, JVM हीप का साइज़ बाइट में (इसके लिए,--memory_profile
को सेट करना ज़रूरी है, जो फ़ुल जीसी को फ़ोर्स करने की कोशिश करता है).
आम तौर पर, बिल्ड अनुरोध के साइज़ की मेट्रिक में गिरावट आने की वजह से, मेमोरी के इस्तेमाल में गिरावट आती है. ऐसा, डिपेंडेंसी जोड़ने या नियम लागू करने के तरीके में बदलाव करने की वजह से होता है.
हमारा सुझाव है कि नियमों के लिए, पहले से मौजूद मेमोरी प्रोफ़ाइलर का इस्तेमाल करके, Bazel के मेमोरी फ़ुटप्रिंट का ज़्यादा बारीकी से विश्लेषण करें.
लगातार काम करने वाले वर्कर के लिए मेमोरी प्रोफ़ाइल बनाना
पर्सिस्टेंट वर्कर्स, खास तौर पर इंटरप्रेट की गई भाषाओं के लिए, बिल्ड को तेज़ी से पूरा करने में मदद कर सकते हैं. हालांकि, इनकी मेमोरी फ़ुटप्रिंट से समस्याएं आ सकती हैं. Bazel, अपने वर्कर्स की मेट्रिक इकट्ठा करता है. खास तौर पर, WorkerMetrics.WorkerStats.worker_memory_in_kb
फ़ील्ड से पता चलता है कि वर्कर्स, मेमोनिक के हिसाब से कितनी मेमोरी का इस्तेमाल करते हैं.
JSON ट्रेस प्रोफ़ाइलर, --experimental_collect_system_network_usage
फ़्लैग (Bazel 6.0 में नया) को पास करके, कॉल के दौरान पर्सिस्टेंट वर्कर्स की मेमोरी के इस्तेमाल की जानकारी भी इकट्ठा करता है.
दूसरी इमेज. ऐसी प्रोफ़ाइल जिसमें वर्कर्स मेमोरी के इस्तेमाल की जानकारी शामिल होती है.
--worker_max_instances
(डिफ़ॉल्ट तौर पर 4) की वैल्यू कम करने से, लगातार काम करने वाले वर्कर्स के लिए इस्तेमाल की जाने वाली मेमोरी कम हो सकती है. हम Bazel के रिसॉर्स मैनेजर और शेड्यूलर को बेहतर बनाने के लिए लगातार काम कर रहे हैं, ताकि आने वाले समय में इस तरह की बारीक सेटिंग की ज़रूरत कम पड़े.
रिमोट बिल्ड के लिए नेटवर्क ट्रैफ़िक को मॉनिटर करना
रिमोट तरीके से प्रोग्राम चलाने पर, Bazel उन आर्टफ़ैक्ट को डाउनलोड करता है जो कार्रवाइयां करने की वजह से बने थे. इसलिए, आपकी नेटवर्क बैंडविथ आपके बिल्ड की परफ़ॉर्मेंस पर असर डाल सकती है.
अगर बिल्ड के लिए रिमोट एक्ज़ीक्यूशन का इस्तेमाल किया जा रहा है, तो हो सकता है कि आप शुरू करने के दौरान, BEP के NetworkMetrics.SystemNetworkStats
प्रोटोकॉल का इस्तेमाल करके नेटवर्क ट्रैफ़िक को मॉनिटर करना चाहें (इसके लिए, --experimental_collect_system_network_usage
पास करना ज़रूरी है).
इसके अलावा, JSON ट्रेस प्रोफ़ाइलों की मदद से, --experimental_collect_system_network_usage
फ़्लैग (Bazel 6.0 में नया) पास करके, पूरे बिल्ड के दौरान सिस्टम-वाइड नेटवर्क के इस्तेमाल को देखा जा सकता है.
तीसरी इमेज. ऐसी प्रोफ़ाइल जिसमें सिस्टम के नेटवर्क के इस्तेमाल की जानकारी शामिल होती है.
रिमोट तरीके से प्रोग्राम चलाने के दौरान, नेटवर्क के इस्तेमाल में उतार-चढ़ाव न होना और उसका इस्तेमाल ज़्यादा होना, इस बात का संकेत हो सकता है कि आपके बिल्ड में नेटवर्क की समस्या है. अगर आपने अब तक इसका इस्तेमाल नहीं किया है, तो --remote_download_minimal
को पास करके, 'बिट के बिना बिल्ड' सुविधा चालू करें.
इससे, ग़ैर-ज़रूरी इंटरमीडिएट आर्टफ़ैक्ट डाउनलोड होने से बचा जा सकेगा और आपके बिल्ड तेज़ी से पूरे हो सकेंगे.
डाउनलोड बैंडविड्थ बचाने के लिए, एक स्थानीय डिस्क कैश कॉन्फ़िगर किया जा सकता है.