डाइनैमिक तरीके से प्रोग्राम चलाना, Bazel की एक सुविधा है. इसमें एक ही कार्रवाई को लोकल और रिमोट, दोनों तरह से एक साथ शुरू किया जाता है. इसके लिए, पहले पूरी होने वाली शाखा के आउटपुट का इस्तेमाल किया जाता है और दूसरी शाखा को रद्द कर दिया जाता है. यह रिमोट बिल्ड सिस्टम की, प्रोग्राम को लागू करने की क्षमता और/या बड़े शेयर किए गए कैश मेमोरी को, स्थानीय तौर पर प्रोग्राम को लागू करने में लगने वाले कम समय के साथ जोड़ता है. इससे, क्लीन और इंक्रीमेंटल, दोनों तरह के बिल्ड के लिए, दोनों ही सिस्टम के फ़ायदे मिलते हैं.
इस पेज पर, डाइनैमिक तरीके से लागू होने की सुविधा को चालू करने, उसे ट्यून करने, और डीबग करने का तरीका बताया गया है. अगर आपको लोकल और रिमोट एक्ज़ीक्यूशन, दोनों को सेट अप किया गया हो और ऐसे में बेज़ल को अडजस्ट करने की कोशिश की जा रही हो सेटिंग की जानकारी देखें, तो यह पेज आपके लिए है. अगर आपने पहले से ही रिमोट रन करने की सुविधा सेट अप नहीं की है, तो सबसे पहले Bazel रिमोट रन करने की सुविधा की खास जानकारी पर जाएं.
क्या डाइनैमिक तरीके से प्रोग्राम चलाने की सुविधा चालू करनी है?
डाइनैमिक एक्सीक्यूशन मॉड्यूल, Bazel का हिस्सा है. हालांकि, डाइनैमिक एक्सीक्यूशन का इस्तेमाल करने के लिए, आपके पास एक ही Bazel सेटअप से, लोकल और रिमोट, दोनों तरह से कंपाइल करने की सुविधा होनी चाहिए.
डाइनैमिक एक्सीक्यूशन मॉड्यूल चालू करने के लिए, Bazel को --internal_spawn_scheduler
फ़्लैग पास करें. इससे, dynamic
नाम की एक नई रणनीति जोड़ी जाती है. अब आपके पास, उन मेमोनेमिक के लिए अपनी रणनीति के तौर पर इसका इस्तेमाल करने का विकल्प है जिन्हें डाइनैमिक तौर पर चलाना है, जैसे कि --strategy=Javac=dynamic
. डायनैमिक तरीके से लागू करने के लिए, कौनसे मेमोनिक चुनने हैं, यह जानने के लिए अगला सेक्शन देखें.
डायनैमिक रणनीति का इस्तेमाल करने वाले किसी भी मेमोनेमिक के लिए, रिमोट तौर पर लागू होने वाली रणनीतियां --dynamic_remote_strategy
फ़्लैग से ली जाती हैं. वहीं, स्थानीय रणनीतियां --dynamic_local_strategy
फ़्लैग से ली जाती हैं. पासिंग
--dynamic_local_strategy=worker,sandboxed
, लोकल पर डिफ़ॉल्ट रूप से सेट करता है
डाइनैमिक एक्ज़ीक्यूशन की ब्रांच को
ऑर्डर. --dynamic_local_strategy=Javac=worker
पास करने पर, सिर्फ़ Javac के लिए डिफ़ॉल्ट सेटिंग बदल जाती है. रिमोट वर्शन इसी तरह से काम करता है. दोनों फ़्लैग यह कर सकते हैं
कई बार तय किया जाना चाहिए. अगर किसी कार्रवाई को स्थानीय तौर पर लागू नहीं किया जा सकता है, तो
सामान्य तरीके से रिमोट तरीके से एक्ज़ीक्यूट किया जाता है. इसी तरह, रिमोट तरीके से भी लागू किया जाता है.
अगर आपके रिमोट सिस्टम में कैश मेमोरी है, तो --dynamic_local_execution_delay
फ़्लैग
रिमोट सिस्टम के होने के बाद, लोकल एक्ज़ीक्यूशन में मिलीसेकंड में देरी होती है
ने कैश हिट दिखाया. इससे, ज़्यादा कैश हिट होने पर, स्थानीय तौर पर एक्सीक्यूशन को चलाने से बचा जा सकता है. डिफ़ॉल्ट वैल्यू 1000 मि॰से॰ है, लेकिन इसे थोड़ा-बहुत देखना चाहिए
से ज़्यादा समय लगता है. असल समय, रिमोट पर निर्भर करता है
और दोतरफ़ा यात्रा में कितना समय लगता है. आम तौर पर, वैल्यू एक जैसी रहती है
किसी दिए गए रिमोट सिस्टम के सभी उपयोगकर्ताओं के लिए, जब तक कि उनमें से कुछ काफ़ी दूर न हों
दोतरफ़ा इंतज़ार का समय जोड़ने के लिए. आपके पास Basel प्रोफ़ाइलिंग
सुविधाओं का इस्तेमाल करके देखा जा सकता है कि
कैश मेमोरी हिट मानी जाती हैं.
डाइनैमिक एक्ज़ीक्यूशन का इस्तेमाल, लोकल सैंडबॉक्स रणनीति के साथ-साथ
स्थायी कर्मचारी. डाइनैमिक तरीके से लागू करने के साथ इस्तेमाल किए जाने पर, पर्सिस्टेंट वर्कर्स अपने-आप सैंडबॉक्सिंग के साथ चलेंगे. साथ ही, मल्टीप्लेक्स वर्कर्स का इस्तेमाल नहीं किया जा सकता. Darwin और Windows सिस्टम पर, सैंडबॉक्स की रणनीति धीमी हो सकती है. इन सिस्टम पर सैंडबॉक्स बनाने के ओवरहेड को कम करने के लिए, --reuse_sandbox_directories
पास किया जा सकता है.
डाइनैमिक तरीके से लागू होने की सुविधा, standalone
रणनीति के साथ भी काम कर सकती है. हालांकि, standalone
रणनीति को लागू होने के दौरान आउटपुट लॉक लेना होता है. इससे, रिमोट रणनीति को पहले लागू होने से रोका जा सकता है. कॉन्टेंट बनाने
--experimental_local_lockfree_output
फ़्लैग इन चीज़ों से इस समस्या को हल करने में मदद करता है
लोकल एक्ज़ीक्यूशन को सीधे आउटपुट में लिखने की अनुमति देता है, लेकिन यह
रिमोट एक्ज़ीक्यूशन को, क्या पहले पूरा करना होगा.
अगर डाइनैमिक तरीके से लागू होने वाली कार्रवाई की कोई शाखा पहले पूरी हो जाती है, लेकिन वह पूरी नहीं होती है, तो पूरी कार्रवाई पूरी नहीं होती. यह जान-बूझकर किया गया विकल्प है, ताकि लोकल और रिमोट रनटाइम के बीच के अंतर को अनदेखा न किया जा सके.
डाइनैमिक एक्ज़ीक्यूशन और लॉक करने की सुविधा के काम करने के तरीके के बारे में ज़्यादा जानने के लिए, जूलियो से संपर्क करें मेरिनो का शानदार ब्लॉग पोस्ट
मुझे डाइनैमिक तरीके से लागू करने का विकल्प कब चुनना चाहिए?
डाइनैमिक तरीके से एक्ज़ीक्यूशन करने के लिए, रिमोट एक्ज़ीक्यूशन सिस्टम की ज़रूरत होती है. फ़िलहाल, सिर्फ़ कैश मेमोरी वाले रिमोट सिस्टम का इस्तेमाल नहीं किया जा सकता, क्योंकि कैश मेमोरी में डेटा न मिलने पर, कार्रवाई पूरी न होने के तौर पर मार्क किया जाएगा.
रिमोट तरीके से एक्ज़ीक्यूट करने के लिए, सभी तरह की कार्रवाइयां सही नहीं होती हैं. सबसे अच्छी उम्मीदवार वे हैं जो स्थानीय रूप से स्वाभाविक रूप से तेज़ होते हैं, उदाहरण के लिए स्थायी कर्मचारियों या तेज़ी से काम करने वाले लोगों का इस्तेमाल करना इतना ही नहीं, एक्ज़ीक्यूशन के समय पर रिमोट एक्ज़ीक्यूशन का काम बढ़ जाता है. से स्थानीय तौर पर लागू की जाने वाली हर कार्रवाई, कुछ सीपीयू और मेमोरी रिसॉर्स को लॉक करती है, ऐसी कार्रवाइयां जो उन कैटगरी में नहीं आती हैं उनसे सिर्फ़ प्रोसेस को पूरा करने में देरी होती है काम में मदद मिलेगी.
रिलीज़ 5.0.0-pre.20210708.4 के बाद, परफ़ॉर्मेंस प्रोफ़ाइलिंग में वर्कर्स के एक्सीक्यूशन का डेटा होता है. इसमें, डाइनैमिक एक्सीक्यूशन रेस में हारने के बाद, किसी वर्क रिक्वेस्ट को पूरा करने में लगने वाला समय भी शामिल होता है. अगर आपको डाइनैमिक टास्क को पूरा करने वाली वर्क थ्रेड, रिसॉर्स हासिल करने में ज़्यादा समय लगाती हैं या async-worker-finish
में ज़्यादा समय बिताती हैं, तो हो सकता है कि कुछ धीमी स्थानीय कार्रवाइयों की वजह से वर्क थ्रेड में देरी हो रही हो.
ऊपर दी गई प्रोफ़ाइल में, जो 8 Javac वर्कर का इस्तेमाल करती है, हमें कई Javac वर्कर दिखते हैं
async-worker-finish
में रेस हार गई और अपना काम पूरा किया
थ्रेड. ऐसा इसलिए हुआ, क्योंकि काम न करने वाले लोगों को याद रखने के लिए ज़रूरी संसाधन चाहिए थे
इससे ज़्यादा समय नहीं लगेगा.
जब सिर्फ़ Javac को डाइनैमिक तरीके से चलाया जाता है, तो शुरू किए गए आधे वर्कर्स ही अपना काम पूरा कर पाते हैं.
पहले सुझाए गए --experimental_spawn_scheduler
फ़्लैग का इस्तेमाल नहीं किया जा सकता.
यह डाइनैमिक एक्ज़ीक्यूशन की सुविधा चालू करता है और dynamic
को सभी के लिए डिफ़ॉल्ट रणनीति के तौर पर सेट करता है
याददाश्त बढ़ाने वाली तकनीक, जिससे अक्सर इस तरह की समस्याएं पैदा होती हैं.
परफ़ॉर्मेंस
डाइनैमिक एक्ज़ीक्यूशन के तरीके में यह माना जाता है कि ज़रूरत के मुताबिक संसाधन उपलब्ध हैं स्थानीय और दूर से भी काम कर रहे हैं और सेवाओं को बेहतर बनाने के लिए कुछ अतिरिक्त संसाधन खर्च किए जा सकते हैं परफ़ॉर्मेंस का डेटा इकट्ठा किया जा सकता है. हालांकि, संसाधनों का बहुत ज़्यादा इस्तेमाल करने से Basel की प्रोसेस धीमी हो सकती है या या रिमोट सिस्टम पर अनचाहा दबाव डालें. डाइनैमिक तरीके से लागू होने की सुविधा के व्यवहार को बदलने के लिए, कई विकल्प उपलब्ध हैं:
--dynamic_local_execution_delay
एक संख्या से स्थानीय शाखा की शुरुआत में देरी करता है
मिलीसेकंड के बाद, रिमोट ब्रांच के शुरू होने के बाद
वर्तमान बिल्ड के दौरान रिमोट कैश हिट होता है. इससे उपयोगकर्ताओं को यह फ़ायदा मिलता है
दूर से कैश मेमोरी में सेव करने से, स्थानीय संसाधनों की बर्बादी नहीं होती है. ऐसा तब होता है, जब इस बात की संभावना ज़्यादा हो कि
आउटपुट, कैश मेमोरी में मिल सकते हैं. कैश मेमोरी की क्वालिटी के आधार पर, इसे कम करने से बिल्ड की स्पीड बेहतर हो सकती है. हालांकि, इसके लिए ज़्यादा लोकल रिसॉर्स का इस्तेमाल करना पड़ सकता है.
--experimental_dynamic_local_load_factor
, संसाधन मैनेज करने का एक बेहतर विकल्प है. फ़िलहाल, इसे एक्सपेरिमेंट के तौर पर उपलब्ध कराया गया है. इस सुविधा को बंद करने के लिए, इसकी वैल्यू 0 से 1 के बीच होनी चाहिए.
जब इसकी वैल्यू 0 से ज़्यादा पर सेट की जाती है, तब Baज़र, कन्वर्ज़न की हर वैल्यू को
स्थानीय तौर पर शेड्यूल की गई कार्रवाइयाँ, जब कई कार्रवाइयाँ
शेड्यूल नहीं होगा. इसे 1 पर सेट करने पर, उतनी कार्रवाइयां शेड्यूल की जा सकती हैं जितनी कार्रवाइयां शेड्यूल की जा सकती हैं
क्या सीपीयू उपलब्ध हैं (--local_cpu_resources
के हिसाब से). कम वैल्यू, संख्या सेट करती हैं
कार्रवाइयों की ज़्यादा संख्या को
चलाने के लिए उपलब्ध है. यह सुनने में अटपटा लग सकता है, लेकिन एक अच्छे रिमोट सिस्टम की मदद से, कई कार्रवाइयां चलने पर, लोकल ऐक्शन से ज़्यादा फ़ायदा नहीं मिलता. साथ ही, लोकल सीपीयू का इस्तेमाल रिमोट ऐक्शन को मैनेज करने में किया जाता है.
--experimental_dynamic_slow_remote_time
, लोकल ब्रांच शुरू करने को प्राथमिकता देता है
जब रिमोट ब्रांच कम से कम इतने समय से चल रही हो. आम तौर पर
हाल ही में शेड्यूल की गई कार्रवाई को प्राथमिकता दी जाती है, क्योंकि इसके पास
दौड़ जीतने के बाद भी, लेकिन अगर रिमोट सिस्टम कभी-कभी रुक जाता है या ज़्यादा समय लगता है,
इससे आगे बढ़ने में मदद मिलती है. यह सुविधा डिफ़ॉल्ट रूप से चालू नहीं होती, क्योंकि इससे रिमोट सिस्टम से जुड़ी समस्याएं छिप सकती हैं. इन समस्याओं को ठीक करना ज़रूरी है. इस विकल्प को चालू करने पर, अपने रिमोट सिस्टम की परफ़ॉर्मेंस को मॉनिटर करना न भूलें.
--experimental_dynamic_ignore_local_signals
का इस्तेमाल, किसी सिग्नल की वजह से स्थानीय स्पैन के बाहर निकलने पर, रिमोट शाखा को कंट्रोल करने के लिए किया जा सकता है. यह मुख्य रूप से, वर्कर्स के लिए संसाधनों की सीमाओं के साथ काम आता है (--experimental_worker_memory_limit_mb
,
--experimental_worker_sandbox_hardening
, और
--experimental_sandbox_memory_limit_mb
). इन सीमाओं के तहत, वर्कर्स की प्रोसेस को तब बंद किया जा सकता है, जब वे बहुत ज़्यादा संसाधनों का इस्तेमाल करें.
JSON ट्रेस प्रोफ़ाइल में, परफ़ॉर्मेंस से जुड़े कई ग्राफ़ होते हैं. इनसे परफ़ॉर्मेंस और संसाधन के इस्तेमाल के बीच के समझौते को बेहतर बनाने के तरीकों का पता चलता है.
समस्या का हल
डाइनैमिक तरीके से लागू करने से जुड़ी समस्याएं, आसानी से नहीं दिखती हैं और उन्हें डीबग करना मुश्किल होता है. ऐसा इसलिए, क्योंकि ये समस्याएं सिर्फ़ स्थानीय और रिमोट तरीके से लागू करने के कुछ खास कॉम्बिनेशन में दिखती हैं.
--debug_spawn_scheduler
, डाइनैमिक एक्सीक्यूशन सिस्टम से अतिरिक्त आउटपुट जोड़ता है, जिससे इन समस्याओं को डीबग करने में मदद मिल सकती है. आपको यह भी तय करना होगा कि
--dynamic_local_execution_delay
फ़्लैग और रिमोट जॉब बनाम लोकल जॉब की संख्या
उसकी मदद से समस्याओं को आसानी से समझा जा सकता है.
अगर आपको standalone
रणनीति का इस्तेमाल करके, डाइनैमिक तरीके से कार्रवाइयां करने में समस्याएं आ रही हैं, तो --experimental_local_lockfree_output
के बिना कार्रवाइयां चलाकर देखें. इसके अलावा, अपनी लोकल कार्रवाइयों को सैंडबॉक्स में चलाकर भी देखें. इससे आपके बिल्ड में थोड़ी देरी हो सकती है (अगर आपके पास Mac या Windows है, तो ऊपर देखें). हालांकि, इससे गड़बड़ियों की कुछ संभावित वजहें हट जाती हैं.