डाइनैमिक एक्ज़ीक्यूशन, Bazel में मौजूद एक सुविधा है. 0.21 के बाद से, इसमें एक ही ऐक्शन को लोकल और रिमोट तौर पर एक साथ चलाया जाता है. इसमें, खत्म होने वाली पहली ब्रांच के आउटपुट का इस्तेमाल करके, दूसरी ब्रांच को रद्द किया जाता है. इसमें रिमोट बिल्ड सिस्टम की एक्ज़ीक्यूशन पावर और/या शेयर की गई कैश मेमोरी को स्थानीय तौर पर एक्ज़ीक्यूट करने में लगने वाला समय कम होना चाहिए. इससे, स्वच्छ और इंक्रीमेंटल बिल्ड के लिए, दोनों के लिए बेहतरीन सुविधाएं मिलती हैं.
इस पेज पर बताया गया है कि डाइनैमिक एक्ज़ीक्यूशन को कैसे चालू करें, ट्यून करें, और डीबग करें. अगर आपने लोकल और रिमोट, दोनों फ़ॉर्मैट में एक्ज़ीक्यूशन किया है और आपको बेहतर परफ़ॉर्मेंस पाने के लिए 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 नीमोनिक
के लिए डिफ़ॉल्ट सेटिंग बदल जाती है. रिमोट वर्शन भी इसी तरह काम करता है. दोनों फ़्लैग के बारे में
एक से ज़्यादा बार बताया जा सकता है. अगर कोई कार्रवाई स्थानीय रूप से नहीं की जा सकती, तो उसे
सामान्य तरीके से रिमोट तरीके से किया जाता है. इसी तरह, अगर कोई कार्रवाई स्थानीय तौर पर नहीं की जा सकती, तो उसे रिमोट तरीके से भी लागू किया जाता है.
अगर आपके रिमोट सिस्टम में कैश मेमोरी है, तो रिमोट सिस्टम की ओर से कैश हिट होने का संकेत मिलने के बाद, --local_execution_delay
फ़्लैग, लोकल एक्ज़ीक्यूशन में मिलीसेकंड में देरी जोड़ता है. इससे, ज़्यादा कैश हिट होने की संभावना होने पर, लोकल एक्ज़ीक्यूट करने की सुविधा
चलाने से बचा जा सकता है. डिफ़ॉल्ट वैल्यू 1000 मि॰से॰ है, लेकिन आम तौर पर कैश हिट
से ज़्यादा समय लगता है. असल समय, रिमोट सिस्टम पर और दोतरफ़ा यात्रा में लगने वाले समय पर निर्भर करता है. आम तौर पर, किसी रिमोट सिस्टम के सभी उपयोगकर्ताओं के लिए
यह वैल्यू एक ही होती है. हालांकि, ऐसा तब तक होता है, जब तक कि दोतरफ़ा यात्रा के लिए लगने वाला समय कम करने
के लिए, उनमें से कुछ काफ़ी दूर हों. Bazel प्रोफ़ाइलिंग सुविधाओं का इस्तेमाल करके, यह पता किया जा सकता है कि आम तौर पर, कैश मेमोरी में सेव होने में कितना समय लगता है.
डाइनैमिक एक्ज़ीक्यूशन का इस्तेमाल, लोकल सैंडबॉक्स की गई रणनीति के साथ
नियमित तौर पर काम करने वाले कर्मचारियों के साथ किया जा सकता है. डाइनैमिक एक्ज़ीक्यूशन के साथ इस्तेमाल करने पर, लगातार काम करने वाले वर्कर, सैंडबॉक्सिंग की मदद से अपने-आप चलते हैं. साथ ही, वे मल्टीप्लेक्स वर्कर का इस्तेमाल नहीं कर सकते. डार्विन और 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
को सभी मेमोरी के लिए डिफ़ॉल्ट रणनीति के तौर पर सेट कर देता है.
इससे अक्सर इस तरह की समस्याएं पैदा होंगी.
समस्या हल करना
डाइनैमिक एक्ज़ीक्यूशन में आने वाली समस्याओं को डीबग करना आसान और मुश्किल हो सकता है, क्योंकि ये लोकल और रिमोट तौर पर एक्ज़ीक्यूशन के कुछ खास कॉम्बिनेशन में ही दिखती हैं.
--debug_spawn_scheduler
, डाइनैमिक एक्ज़ीक्यूशन सिस्टम से अतिरिक्त आउटपुट जोड़ता है
जो इन समस्याओं को डीबग करने में मदद कर सकता है. समस्याओं को फिर से सामने लाने के लिए, --local_execution_delay
फ़्लैग और रिमोट बनाम लोकल जॉब की संख्या में भी बदलाव किया जा सकता है.
अगर आपको standalone
रणनीति का इस्तेमाल करके, डाइनैमिक एक्ज़ीक्यूशन में समस्या आ रही है, तो --experimental_local_lockfree_output
के बिना चलाएं या अपने लोकल ऐक्शन को सैंडबॉक्स करके चलाएं. यह आपके बिल्ड को थोड़ा धीमा कर सकता है (अगर आप Mac या Windows
का इस्तेमाल कर रहे हैं, तो ऊपर देखें), लेकिन यह गड़बड़ी की कुछ संभावित वजहों को हटा देता है.