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

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

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

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

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

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

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

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

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

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

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

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

    • रिग्रेशन को डीबग करने के लिए, aquery का इस्तेमाल करें. हमारा सुझाव है कि --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 का इस्तेमाल करके, बिल्ड को विश्लेषण के फ़ेज़ तक सीमित रखना चाहिए, क्योंकि सीपीयू का ज़्यादातर काम यहीं होता है.
  • सिस्टम टाइम, सीपीयू के कर्नेल में बिताया गया समय होता है.

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

डाउनलोड बैंडविड्थ बचाने के लिए, एक स्थानीय डिस्क कैश मेमोरी कॉन्फ़िगर करने का भी विकल्प है.