Bazel एक जटिल टूल है. यह बिल्ड के दौरान कई अलग-अलग काम करता है. इनमें से कुछ कामों से, बिल्ड की परफ़ॉर्मेंस पर असर पड़ सकता है. इस पेज पर, Bazel के कुछ कॉन्सेप्ट को बिल्ड की परफ़ॉर्मेंस पर पड़ने वाले उनके असर से मैप करने की कोशिश की गई है. हमने कुछ ऐसे उदाहरण शामिल किए हैं जिनसे यह पता चलता है कि मेट्रिक निकालकर, बिल्ड की परफ़ॉर्मेंस से जुड़ी समस्याओं का पता कैसे लगाया जा सकता है. साथ ही, इन समस्याओं को ठीक करने के लिए क्या किया जा सकता है. हमें उम्मीद है कि बिल्ड की परफ़ॉर्मेंस में गिरावट की जांच करते समय, इन कॉन्सेप्ट को लागू किया जा सकेगा.
क्लीन बिल्ड बनाम इंक्रीमेंटल बिल्ड
क्लीन बिल्ड में, सब कुछ नए सिरे से बनाया जाता है. वहीं, इंक्रीमेंटल बिल्ड में, पहले से पूरा किए गए कुछ काम को फिर से इस्तेमाल किया जाता है.
हमारा सुझाव है कि क्लीन और इंक्रीमेंटल बिल्ड को अलग-अलग देखें. ऐसा खास तौर पर तब करें, जब Bazel के कैश की स्थिति पर निर्भर मेट्रिक इकट्ठा या एग्रीगेट की जा रही हों. उदाहरण के लिए, बिल्ड के अनुरोध के साइज़ की मेट्रिक. ये दोनों, उपयोगकर्ता के दो अलग-अलग अनुभव भी दिखाते हैं. क्लीन बिल्ड को नए सिरे से शुरू करने में ज़्यादा समय लगता है, क्योंकि इसमें कैश खाली होता है. इसके मुकाबले, इंक्रीमेंटल बिल्ड ज़्यादा बार किए जाते हैं, क्योंकि डेवलपर कोड में बार-बार बदलाव करते हैं. आम तौर पर, इंक्रीमेंटल बिल्ड तेज़ी से होते हैं, क्योंकि कैश आम तौर पर पहले से भरा होता है.
बिल्ड को कैटगरी में बांटने के लिए, BEP में CumulativeMetrics.num_analyses फ़ील्ड का इस्तेमाल किया जा सकता है. अगर num_analyses <= 1 है, तो यह क्लीन बिल्ड है. इसके अलावा, इसे आम तौर पर
इंक्रीमेंटल बिल्ड के तौर पर कैटगरी में बांटा जा सकता है. ऐसा हो सकता है कि उपयोगकर्ता ने अलग-अलग फ़्लैग या अलग-अलग टारगेट पर स्विच किया हो.
इससे, बिल्ड असल में क्लीन बिल्ड बन गया हो. इंक्रीमेंटल बिल्ड की ज़्यादा सटीक परिभाषा, अनुमान के तौर पर दी जा सकती है. उदाहरण के लिए, लोड किए गए पैकेज की संख्या (PackageMetrics.packages_loaded) देखना.
बिल्ड की परफ़ॉर्मेंस के लिए, डिटरमिनिस्टिक बिल्ड मेट्रिक का इस्तेमाल करना
बिल्ड की परफ़ॉर्मेंस को मेज़र करना मुश्किल हो सकता है, क्योंकि कुछ मेट्रिक डिटरमिनिस्टिक नहीं होती हैं. उदाहरण के लिए, 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 से जुड़ा होता है. ऐसा तब होता है, जब 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()को कॉल करने के बाद, इस्तेमाल की गई मेमोरी की मात्रा (बाइट में).- Bazel bench इस मेट्रिक के लिए बेंचमार्क भी उपलब्ध कराता है.
- इसके अलावा,
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 फ़ील्ड से पता चलता है कि वर्कर, नेमोनिक के हिसाब से कितनी मेमोरी इस्तेमाल करते हैं.
JSON ट्रेस
प्रोफ़ाइलर, इनवोकेशन के दौरान
पर्सिस्टेंट वर्कर की मेमोरी के इस्तेमाल की जानकारी भी इकट्ठा करता है. इसके लिए,
--experimental_collect_system_network_usage
फ़्लैग (Bazel 6.0 में नया) पास करना होता है.

दूसरी इमेज. ऐसी प्रोफ़ाइल जिसमें वर्कर की मेमोरी के इस्तेमाल की जानकारी शामिल है.
--worker_max_instances
की वैल्यू (डिफ़ॉल्ट 4) कम करने से, पर्सिस्टेंट
वर्कर की ओर से इस्तेमाल की जाने वाली मेमोरी की मात्रा को कम करने में मदद मिल सकती है. हम Bazel के रिसॉर्स मैनेजर और शेड्यूलर को बेहतर बनाने के लिए लगातार काम कर रहे हैं, ताकि आने वाले समय में इस तरह की फ़ाइन ट्यूनिंग की ज़रूरत कम पड़े.
रिमोट बिल्ड के लिए नेटवर्क ट्रैफ़िक की निगरानी करना
रिमोट एक्ज़ीक्यूशन में, Bazel उन आर्टफ़ैक्ट को डाउनलोड करता है जो कार्रवाइयों को एक्ज़ीक्यूट करने के बाद बनाए गए थे. इसलिए, आपके नेटवर्क बैंडविड्थ से, बिल्ड की परफ़ॉर्मेंस पर असर पड़ सकता है.
अगर अपने बिल्ड के लिए रिमोट एक्ज़ीक्यूशन का इस्तेमाल किया जा रहा है, तो आपको
इनवोकेशन के दौरान नेटवर्क ट्रैफ़िक की निगरानी करने के लिए
NetworkMetrics.SystemNetworkStats प्रोटो का इस्तेमाल करना चाहिए. इसके लिए
BEP से
--experimental_collect_system_network_usage पास करना ज़रूरी है.
इसके अलावा, JSON ट्रेस
प्रोफ़ाइल की मदद से, बिल्ड के दौरान सिस्टम-वाइड नेटवर्क के इस्तेमाल की जानकारी देखी जा सकती है. इसके लिए,
--experimental_collect_system_network_usage फ़्लैग (Bazel
6.0 में नया) पास करना होता है.

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