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 पास करके, 'बाइट के बिना बिल्ड करें' सुविधा चालू करें.
इससे गैर-ज़रूरी इंटरमीडिएट आर्टफ़ैक्ट डाउनलोड नहीं किए जाएंगे. इसलिए, बिल्ड तेज़ी से तैयार होंगे.
डाउनलोड बैंडविथ को बचाने के लिए, लोकल डिस्क कैश मेमोरी को कॉन्फ़िगर किया जा सकता है.