इस पेज पर, पर्सिस्टेंट वर्कर्स का इस्तेमाल करने का तरीका, फ़ायदे, ज़रूरी शर्तें, और वर्कर्स के सैंडबॉक्सिंग पर पड़ने वाले असर के बारे में बताया गया है.
पर्सिस्टेंट वर्कर्स, लंबे समय तक चलने वाली प्रोसेस होती हैं. इन्हें Bazel सर्वर शुरू करता है. ये प्रोसेस, असल टूल (आम तौर पर कंपाइलर) के रैपर के तौर पर काम करती हैं या खुद ही टूल होती हैं. लगातार काम करने वाले वर्कर्स का फ़ायदा पाने के लिए, टूल को एक से ज़्यादा बार कंपाइल करने की सुविधा देनी होगी. साथ ही, रैपर को टूल के एपीआई और नीचे बताए गए अनुरोध/रिस्पॉन्स फ़ॉर्मैट के बीच अनुवाद करना होगा. एक ही बिल्ड में, एक ही वर्कर्स को --persistent_worker
फ़्लैग के साथ और उसके बिना कॉल किया जा सकता है. साथ ही, टूल को सही तरीके से शुरू करने और उससे बातचीत करने के साथ-साथ, बाहर निकलने पर वर्कर्स को बंद करने की ज़िम्मेदारी भी इसकी होती है. हर वर्क इंस्टेंस को <outputBase>/bazel-workers
के तहत एक अलग वर्किंग डायरेक्ट्री असाइन की जाती है. हालांकि, उसमें chroot नहीं किया जाता.
लगातार काम करने वाले लोगों का इस्तेमाल करना एक्ज़िक्यूशन की रणनीति जिससे घटती हो स्टार्ट-अप ओवरहेड करते हैं. इससे ज़्यादा JIT कंपाइलेशन मिलता है. साथ ही, उदाहरण के लिए, ऐक्शन एक्ज़ीक्यूशन में ऐब्स्ट्रैक्ट सिंटैक्स ट्री. यह रणनीति लंबे समय से चलने वाले विज्ञापन ग्रुप के लिए कई अनुरोध भेजकर, इन सुधारों को लागू करती है प्रोसेस.
स्थायी वर्कर को कई भाषाओं में लागू किया जाता है. इनमें Java, स्काला, Kotlin वगैरह.
NodeJS रनटाइम का इस्तेमाल करने वाले प्रोग्राम, @bazel/worker हेल्पर लाइब्रेरी वर्कर प्रोटोकॉल को लागू करना चाहिए.
स्थायी कर्मचारियों का इस्तेमाल करना
Basel 0.27 और उसके बाद के वर्शन
बिल्ड को एक्ज़ीक्यूट करते समय परसिस्टेंट वर्कर का इस्तेमाल डिफ़ॉल्ट रूप से करता है, हालांकि रिमोट के तौर पर
निष्पादन को प्राथमिकता दी जाती है. जिन कार्रवाइयों के लिए पर्सिस्टेंट वर्कर्स काम नहीं करते उनके लिए,
Bazel हर कार्रवाई के लिए टूल इंस्टेंस शुरू करता है. लागू टूल के नेमनेमोनिक के लिए worker
रणनीति सेट करके, अपने बिल्ड को साफ़ तौर पर, स्थायी वर्कर्स का इस्तेमाल करने के लिए सेट किया जा सकता है. सबसे सही तरीके के तौर पर, इस उदाहरण में local
को worker
रणनीति के लिए फ़ॉलबैक के तौर पर बताया गया है:
bazel build //my:target --strategy=Javac=worker,local
स्थानीय रणनीति के बजाय कर्मचारियों की रणनीति का इस्तेमाल करने से, कंपाइलेशन को बढ़ावा मिल सकता है तेज़ी से काम करता है. Java के लिए, बिल्ड 2 से 4 हो सकते हैं गुना ज़्यादा तेज़, कभी-कभी ज़्यादा तेज़ी से कंपाइल करने की सुविधा मिलती है. बेज़ल का कंपाइल किया जा रहा है कर्मचारियों के साथ करीब 2.5 गुना तेज़ी से काम करता है. ज़्यादा जानकारी के लिए, यह देखें "कर्मचारियों की संख्या चुनना" सेक्शन में जाएं.
अगर आपके पास ऐसा रिमोट बिल्ड एनवायरमेंट है जो आपके लोकल बिल्ड से मेल खाता है
तो आपको परफ़ॉर्मेंस की जांच करने के लिए,
डाइनैमिक रणनीति,
जहां रिमोट तरीके से एक्ज़ीक्यूट किया जा सकता है और कर्मचारी को एक्ज़ीक्यूट किया जा सकता है. डाइनैमिक रणनीति चालू करने के लिए, --experimental_spawn_scheduler फ़्लैग पास करें. यह रणनीति, वर्कर्स को अपने-आप चालू कर देती है. इसलिए, worker
रणनीति तय करने की ज़रूरत नहीं है. हालांकि, फ़ॉलबैक के तौर पर अब भी local
या sandboxed
का इस्तेमाल किया जा सकता है.
कर्मचारियों की संख्या चुनना
हर मेनिमोन के लिए, वर्कर्स इंस्टेंस की डिफ़ॉल्ट संख्या चार होती है. हालांकि, इसमें बदलाव किया जा सकता है. इसके लिए, worker_max_instances
फ़्लैग का इस्तेमाल करें. उपलब्ध सीपीयू का अच्छा इस्तेमाल करने और JIT कंपाइलेशन और कैश मेमोरी में हिट की संख्या के बीच एक समझौता होता है. जितने ज़्यादा कर्मचारी होंगे, उतने ज़्यादा
टारगेट, बिना JITed कोड को चलाने और सर्वर को सुरक्षित रखने के लिए, स्टार्ट-अप की लागत का भुगतान करेंगे
कैश मेमोरी में सेव करता है. अगर आपके पास बनाने के लिए बहुत कम लक्ष्य हैं, तो एक ही कर्मचारी
कम्पाइलेशन की स्पीड और संसाधन के इस्तेमाल के बीच सही तालमेल बनाना (उदाहरण के लिए,
समस्या #8586 देखें.
worker_max_instances
फ़्लैग, हर स्मृति चिह्न और फ़्लैग सेट (नीचे देखें) के लिए, वर्कर्स इंस्टेंस की ज़्यादा से ज़्यादा संख्या सेट करता है. इसलिए, अगर डिफ़ॉल्ट वैल्यू को बनाए रखा जाता है, तो मिक्स किए गए सिस्टम में काफ़ी ज़्यादा रैम का इस्तेमाल किया जा सकता है. इंक्रीमेंटल बिल्ड के लिए, एक से ज़्यादा वर्कर्स इंस्टेंस का फ़ायदा और भी कम होता है.
इस ग्राफ़ में, 64 जीबी रैम वाले 6-कोर हाइपर-थ्रेडेड Intel Xeon 3.5 GHz Linux वर्कस्टेशन पर, Bazel (टारगेट//src:bazel
) के लिए, शुरू से कंपाइल करने में लगने वाला समय दिखाया गया है. हर वर्कर कॉन्फ़िगरेशन के लिए, पांच क्लीन बिल्ड चलाए जाते हैं और
अंतिम चार का औसत निकाला जाता है.
पहला डायग्राम. क्लीन बिल्ड की परफ़ॉर्मेंस में हुए सुधारों का ग्राफ़.
इस कॉन्फ़िगरेशन में, दो वर्कर सबसे तेज़ कंपाइलेशन देते हैं. हालांकि, यह सिर्फ़ 14% होता है एक कर्मचारी की तुलना में सुधार हुआ. अगर आपको अपने संगठन के लिए, कम मेमोरी का इस्तेमाल करते हैं.
आम तौर पर, इंक्रीमेंटल कंपाइलेशन के ज़्यादा फ़ायदे मिलते हैं. क्लीन बिल्ड हालांकि, कंपाइलेशन के बीच किसी एक फ़ाइल में बदलाव करना सामान्य है. खास तौर पर, टेस्ट-ड्रिवन डेवलपमेंट के लिए. ऊपर दिए गए उदाहरण में, कुछ ऐसी कार्रवाइयां भी हैं जो Java के बजाय किसी दूसरी भाषा में की गई हैं. इनसे, इंक्रीमेंटल कंपाइल करने में लगने वाले समय पर असर पड़ सकता है.
AbstractContainerizingSandboxedSpawn.java में मौजूद किसी इंटरनल स्ट्रिंग कॉन्स्टेंट को बदलने के बाद, सिर्फ़ Java सोर्स को फिर से कॉम्पाइल करने (//src/main/java/com/google/devtools/build/lib/bazel:BazelServer_deploy.jar
) पर, प्रोसेस की स्पीड तीन गुना बढ़ जाती है. इसमें, एक वॉर्मअप बिल्ड को छोड़कर, औसतन 20 इंक्रीमेंटल बिल्ड होते हैं:
दूसरी इमेज. इंक्रीमेंटल बिल्ड की परफ़ॉर्मेंस में हुए सुधारों का ग्राफ़.
स्पीड अप बदलाव, किए गए बदलाव पर निर्भर करता है. गुणनखंड 6 का स्पीड-अप है ऊपर दी गई स्थिति में मापा जाता है. ऐसा तब होता है, जब आम तौर पर इस्तेमाल होने वाला कॉन्सटेंट बदलता है.
स्थायी कर्मचारियों में बदलाव करना
वर्कर्स को स्टार्ट-अप फ़्लैग की जानकारी देने के लिए, --worker_extra_flag
फ़्लैग पास किया जा सकता है. उदाहरण के लिए,
--worker_extra_flag=javac=--debug
पास करने से सिर्फ़ Javac के लिए डीबग करने की सुविधा चालू होती है.
इस फ़्लैग के इस्तेमाल के लिए, सिर्फ़ एक वर्कफ़्लैग सेट किया जा सकता है. साथ ही, यह सिर्फ़ एक मेमोनिक के लिए सेट किया जा सकता है.
वर्कर्स को हर मेनिमोन के लिए अलग से नहीं बनाया जाता, बल्कि उनके स्टार्ट-अप फ़्लैग में होने वाले बदलावों के लिए भी बनाया जाता है. याददाश्त बढ़ाने वाले और स्टार्ट-अप का हर कॉम्बिनेशन
फ़्लैग को WorkerKey
में जोड़ा जाता है और हर WorkerKey
के लिए ज़्यादा से ज़्यादा
worker_max_instances
वर्कर बनाए जा सकते हैं. अगले सेक्शन में देखें कि ऐक्शन कॉन्फ़िगरेशन, सेट-अप फ़्लैग की जानकारी कैसे दे सकता है.
Google आपके यूआरएल पैरामीटर को कैसे इस्तेमाल करेगा, यह तय करने के लिए
--high_priority_workers
फ़्लैग का इस्तेमाल करें और याद रखने के लिए इस्तेमाल करें कि इसे सामान्य प्राथमिकता के आधार पर चलाया जाए
याददाश्त बढ़ाने वाली चीज़ें. इससे उन कार्रवाइयों को प्राथमिकता देने में मदद मिल सकती है जो हमेशा क्रिटिकल पाथ में होती हैं. अगर ज़्यादा प्राथमिकता वाले दो या उससे ज़्यादा कर्मचारी अनुरोध पर कार्रवाई करते हैं, तो सभी
अन्य कर्मचारियों को दौड़ने से रोका गया है. इस फ़्लैग का इस्तेमाल एक से ज़्यादा बार किया जा सकता है.
पास कर रहे हैं
--worker_sandboxing
फ़्लैग की मदद से हर वर्कर अनुरोध पर, एक अलग सैंडबॉक्स डायरेक्ट्री का इस्तेमाल होता है,
इनपुट. सैंडबॉक्स को सेट अप करने में कुछ ज़्यादा समय लगता है. खास तौर पर, macOS पर. हालांकि, इससे आपको सही तरीके से काम करने की बेहतर गारंटी मिलती है.
कॉन्टेंट बनाने
--worker_quit_after_build
फ़्लैग का इस्तेमाल मुख्य रूप से डीबग करने और प्रोफ़ाइल बनाने के लिए किया जाता है. यह फ़्लैग सभी कर्मचारियों को बलात्कार करता है
बिल्ड पूरा होने के बाद बंद कर सकते हैं. यहां भी आपको
--worker_verbose
से
इससे आपको पता चलता है कि कर्मचारी क्या कर रहे हैं. यह फ़्लैग, WorkRequest
के verbosity
फ़ील्ड में दिखता है. इससे वर्कर्स को लागू करने के बारे में ज़्यादा जानकारी मिलती है.
कर्मचारी अपने लॉग <outputBase>/bazel-workers
डायरेक्ट्री में इस सेवा के लिए सेव करते हैं:
उदाहरण
/tmp/_bazel_larsrc/191013354bebe14fdddae77f2679c3ef/bazel-workers/worker-1-Javac.log
.
फ़ाइल के नाम में वर्कर आईडी और मेनेमोनिक, दोनों शामिल हैं. हर स्मृति सहायक के लिए एक से ज़्यादा WorkerKey
हो सकते हैं. इसलिए, आपको किसी स्मृति सहायक के लिए worker_max_instances
से ज़्यादा लॉग फ़ाइलें दिख सकती हैं.
Android बिल्ड के लिए, Android बिल्ड की परफ़ॉर्मेंस वाले पेज पर जाएं.
लगातार काम करने वाले कर्मचारियों को लागू करना
वर्कर्स बनाने के तरीके के बारे में ज़्यादा जानकारी के लिए, परसिस्टेंट वर्कर्स बनाना पेज देखें.
यह उदाहरण, JSON का इस्तेमाल करने वाले वर्कर के लिए Starlark कॉन्फ़िगरेशन दिखाता है:
args_file = ctx.actions.declare_file(ctx.label.name + "_args_file")
ctx.actions.write(
output = args_file,
content = "\n".join(["-g", "-source", "1.5"] + ctx.files.srcs),
)
ctx.actions.run(
mnemonic = "SomeCompiler",
executable = "bin/some_compiler_wrapper",
inputs = inputs,
outputs = outputs,
arguments = [ "-max_mem=4G", "@%s" % args_file.path],
execution_requirements = {
"supports-workers" : "1", "requires-worker-protocol" : "json" }
)
इस परिभाषा के साथ, सबसे पहले इस कार्रवाई का इस्तेमाल, एक्ज़ीक्यूट करने से होगा
कमांड लाइन /bin/some_compiler -max_mem=4G --persistent_worker
. Foo.java
को कंपाइल करने का अनुरोध, कुछ ऐसा दिखेगा:
ध्यान दें: प्रोटोकॉल बफ़र स्पेसिफ़िकेशन में "स्नेक केस" (request_id
) का इस्तेमाल किया जाता है, जबकि JSON प्रोटोकॉल में "कैमल केस" (requestId
) का इस्तेमाल किया जाता है. इस दस्तावेज़ में, हम JSON के उदाहरणों में कैमल केस का इस्तेमाल करेंगे. हालांकि, प्रोटोकॉल के बावजूद फ़ील्ड के बारे में बात करते समय, स्नेक केस का इस्तेमाल करेंगे.
{
"arguments": [ "-g", "-source", "1.5", "Foo.java" ]
"inputs": [
{ "path": "symlinkfarm/input1", "digest": "d49a..." },
{ "path": "symlinkfarm/input2", "digest": "093d..." },
],
}
वर्कर को यह डेटा, stdin
पर न्यूलाइन डीलिमिटेड JSON फ़ॉर्मैट में मिलता है, क्योंकि requires-worker-protocol
को JSON पर सेट किया गया है. इसके बाद, वर्कर्स ऐक्शन करता है और अपने स्टैंडआउट पर, Bazel को JSON फ़ॉर्मैट में WorkResponse
भेजता है. इसके बाद, Bazel इस जवाब को पार्स करता है और मैन्युअल तरीके से इसे WorkResponse
प्रोटो में बदल देता है. यहां की यात्रा पर हूं
संबंधित कर्मचारी से संपर्क करने के लिए 'बाइनरी-एन्कोडेड प्रोटोबफ़' का इस्तेमाल करना
JSON, requires-worker-protocol
को proto
पर सेट किया जाएगा, जैसे कि:
execution_requirements = {
"supports-workers" : "1" ,
"requires-worker-protocol" : "proto"
}
अगर आपने प्रोग्राम चलाने से जुड़ी ज़रूरी शर्तों में requires-worker-protocol
शामिल नहीं किया है, तो Bazel डिफ़ॉल्ट रूप से, प्रोग्राम के बीच डेटा भेजने के लिए protobuf का इस्तेमाल करेगा.
बेज़ल WorkerKey
को स्मोनिक और शेयर किए गए झंडों से लिया है. इसलिए, अगर यह
कॉन्फ़िगरेशन की वजह से max_mem
पैरामीटर बदलने की अनुमति है, तो एक अलग वर्कर
इस्तेमाल की जाने वाली हर वैल्यू के लिए जनरेट की जाएगी. इसकी वजह से, डिवाइस की मेमोरी बहुत ज़्यादा खर्च हो सकती है, अगर
बहुत सारी वैरिएशन का इस्तेमाल किया गया है.
फ़िलहाल, हर वर्कर्स एक बार में सिर्फ़ एक अनुरोध प्रोसेस कर सकता है. एक्सपेरिमेंट के तौर पर उपलब्ध मल्टीप्लेक्स वर्कर सुविधा, एक से ज़्यादा प्रॉम्प्ट थ्रेड, अगर दिया गया टूल मल्टीथ्रेड वाला है और रैपर इस पर सेट है उसे समझें.
तय सीमा में GitHub का यह रेपो, उदाहरण के लिए, Java और Python में लिखे गए वर्कर रैपर को भी देखा जा सकता है. अगर आपको JavaScript या TypeScript में काम कर रहे हों, तो @batz का/worker पैकेज और नोडेज वर्कर का उदाहरण मदद मिल सकती है.
वर्कर्स, सैंडबॉक्सिंग पर कैसे असर डालते हैं?
डिफ़ॉल्ट रूप से worker
कार्यनीति का उपयोग करने से कार्रवाई
सैंडबॉक्स, local
रणनीति से मिलता-जुलता है. सैंडबॉक्स में सभी वर्कर्स को चलाने के लिए, --worker_sandboxing
फ़्लैग सेट किया जा सकता है. इससे यह पक्का किया जा सकता है कि टूल के हर एक बार चलने पर, सिर्फ़ वे इनपुट फ़ाइलें दिखें जो उसमें होनी चाहिए. हालांकि, यह टूल अब भी अनुरोधों के बीच, इंटरनल तौर पर जानकारी लीक कर सकता है. उदाहरण के लिए, कैश मेमोरी के ज़रिए. dynamic
रणनीति का इस्तेमाल करने के लिए,
सर्वर वर्कर को सैंडबॉक्स में रखना ज़रूरी है.
वर्कर्स के साथ कंपाइलर कैश मेमोरी का सही इस्तेमाल करने के लिए, हर इनपुट फ़ाइल के साथ एक डाइजेस्ट पास किया जाता है. इसलिए, कंपाइलर या रैपर यह जांच कर सकता है कि इनपुट तब भी मान्य रहेगा, जब आपको फ़ाइल पढ़ने की ज़रूरत न पड़े.
यहां तक कि अनचाही कैशिंग, सैंडबॉक्स किए गए खतरों से बचाने के लिए इनपुट डाइजेस्ट का इस्तेमाल करते समय भी इसमें काम करने वाले लोग, प्योर सैंडबॉक्स के मुकाबले कम सख्त सैंडबॉक्सिंग की सुविधा देते हैं, क्योंकि पिछले अनुरोधों की वजह से प्रभावित दूसरी अंदरूनी स्थिति को बनाए रखना.
मल्टीप्लेक्स वर्कर को सिर्फ़ तब सैंडबॉक्स किया जा सकता है, जब वर्कर को लागू करने पर यह काम करता हो.
और यह सैंडबॉक्सिंग सुविधा,
--experimental_worker_multiplex_sandboxing
फ़्लैग. ज़्यादा जानकारी के लिए, डिज़ाइन दस्तावेज़ देखें).
इसके बारे में और पढ़ें
लगातार काम करने वाले वर्कर के बारे में ज़्यादा जानकारी के लिए, ये देखें:
- ओरिजनल पर्सिस्टेंट वर्कर्स ब्लॉग पोस्ट
- हैस्केल लागू करने के बारे में जानकारी
- माइक मोरार्टी की ब्लॉग पोस्ट
- Bze> के साथ फ़्रंट एंड डेवलपमेंट: ऐंग्युलर/टाइपस्क्रिप्ट और परसिस्टेंट वर्कर आसाना के साथ
- Bazel की रणनीतियों के बारे में जानकारी
- bazel-discuss मेलिंग सूची पर, काम करने वालों की रणनीति के बारे में जानकारी