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

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