डाइनैमिक एक्ज़ीक्यूशन

समस्या की शिकायत करें सोर्स देखें

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

इस पेज पर बताया गया है कि डाइनैमिक एक्ज़ीक्यूशन को कैसे चालू करें, ट्यून करें, और डीबग करें. अगर आपने लोकल और रिमोट, दोनों फ़ॉर्मैट में एक्ज़ीक्यूशन किया है और आपको बेहतर परफ़ॉर्मेंस पाने के लिए 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 मि॰से॰ है, लेकिन आम तौर पर कैश हिट से थोड़ा ज़्यादा समय लेती है. असल समय, रिमोट सिस्टम और दोतरफ़ा यात्रा में लगने वाला समय, दोनों पर निर्भर करता है. आम तौर पर, किसी दिए गए रिमोट सिस्टम के सभी उपयोगकर्ताओं के लिए वैल्यू एक जैसी होती है. हालांकि, ऐसा तब तक होता है, जब तक दोतरफ़ा यात्रा के समय को जोड़ने के लिए उनमें से कुछ काफ़ी दूर हों. 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 को सभी मेमोरी के लिए डिफ़ॉल्ट रणनीति के तौर पर सेट कर देता है. इससे अक्सर इस तरह की समस्याएं पैदा होंगी.

परफ़ॉर्मेंस

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

रिमोट ब्रांच के चालू होने के बाद, --dynamic_local_execution_delay किसी लोकल ब्रांच के शुरू होने में कई मिलीसेकंड तक देरी करता है. हालांकि, ऐसा सिर्फ़ तब होता है, जब मौजूदा बिल्ड के दौरान रिमोट कैश हिट हो. इससे ऐसे बिल्ड मिलते हैं जो रिमोट कैश से फ़ायदा पाते हैं. इससे स्थानीय संसाधनों की बर्बादी नहीं होती, क्योंकि ज़्यादातर आउटपुट कैश मेमोरी में मिल सकते हैं. कैश मेमोरी की क्वालिटी के हिसाब से इसे कम करने से, बिल्ड करने की स्पीड बढ़ सकती है. इससे स्थानीय संसाधनों को कम खर्च करना पड़ता है.

--experimental_dynamic_local_load_factor, बेहतर रिसॉर्स मैनेजमेंट का प्रयोग है. 0 से 1 तक की कोई भी वैल्यू लग सकती है. इस सुविधा को 0 बंद कर दिया जाएगा. अगर कोई कार्रवाई 0 से ज़्यादा पर सेट है, तो Bazel स्थानीय स्तर पर शेड्यूल की गई कार्रवाइयों की संख्या को अडजस्ट कर देगा. अगर इसे 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 का इस्तेमाल कर रहे हैं, तो ऊपर देखें), लेकिन यह गड़बड़ी की कुछ संभावित वजहों को हटा देता है.