این صفحه نحوه استفاده از کارگران مداوم، مزایا، الزامات و نحوه تأثیر کارگران بر سندباکس را پوشش می دهد.
یک کارگر دائمی یک فرآیند طولانی مدت است که توسط سرور Bazel آغاز شده است، که به عنوان یک بسته بندی در اطراف ابزار واقعی (معمولاً یک کامپایلر) یا خود ابزار عمل می کند. به منظور بهره مندی از کارگران مداوم، ابزار باید از انجام دنباله ای از کامپایل ها پشتیبانی کند و wrapper باید بین API ابزار و فرمت درخواست/پاسخ توضیح داده شده در زیر ترجمه کند. همان کارگر ممکن است با و بدون پرچم --persistent_worker
در همان بیلد فراخوانی شود و مسئول راه اندازی مناسب و صحبت کردن با ابزار و همچنین خاموش کردن کارگران در هنگام خروج است. به هر نمونه کارگر یک دایرکتوری کاری جداگانه در زیر <outputBase>/bazel-workers
اختصاص داده شده است (اما نه به کروت).
استفاده از کارگران دائمی یک استراتژی اجرایی است که سربار راه اندازی را کاهش می دهد، امکان کامپایل JIT بیشتری را فراهم می کند و به عنوان مثال درخت های نحو انتزاعی را در حافظه پنهان در اجرای عمل فعال می کند. این استراتژی با ارسال درخواست های متعدد به یک فرآیند طولانی مدت به این پیشرفت ها دست می یابد.
کارگران دائمی برای چندین زبان از جمله جاوا، اسکالا ، کاتلین و غیره پیادهسازی میشوند.
برنامه هایی که از زمان اجرا NodeJS استفاده می کنند می توانند از کتابخانه کمکی @bazel/worker برای پیاده سازی پروتکل کارگر استفاده کنند.
استفاده از کارگران مداوم
Bazel 0.27 و بالاتر هنگام اجرای بیلدها به طور پیش فرض از کارگران مداوم استفاده می کند، اگرچه اجرای از راه دور اولویت دارد. برای اقداماتی که از کارگران مداوم پشتیبانی نمیکنند، Bazel به شروع یک نمونه ابزار برای هر اقدام بازمیگردد. میتوانید با تنظیم استراتژی worker
برای یادگاری ابزار قابل اجرا، ساخت خود را به صراحت تنظیم کنید تا از کارگران پایدار استفاده کند. به عنوان بهترین روش، این مثال شامل مشخص کردن local
به عنوان بازگشتی به استراتژی worker
است:
bazel build //my:target --strategy=Javac=worker,local
استفاده از استراتژی کارگران به جای استراتژی محلی می تواند بسته به اجرا، سرعت کامپایل را به میزان قابل توجهی افزایش دهد. برای جاوا، بیلدها می توانند 2 تا 4 برابر سریعتر باشند، گاهی اوقات برای کامپایل تدریجی بیشتر. سرعت کامپایل Bazel با کارگران حدود 2.5 برابر است. برای جزئیات بیشتر، بخش " انتخاب تعداد کارگران " را ببینید.
اگر یک محیط ساخت از راه دور نیز دارید که با محیط ساخت محلی شما مطابقت دارد، می توانید از استراتژی دینامیک آزمایشی استفاده کنید که یک اجرای از راه دور و یک اجرای کارگری را انجام می دهد. برای فعال کردن استراتژی پویا، پرچم --experimental_spawn_scheduler را ارسال کنید. این استراتژی به طور خودکار کارگران را فعال می کند، بنابراین نیازی به تعیین استراتژی worker
نیست، اما همچنان می توانید از local
یا sandboxed
به عنوان جایگزین استفاده کنید.
انتخاب تعداد کارگران
تعداد پیشفرض نمونههای کارگر در هر یادگاری 4 است، اما میتوان آن را با پرچم worker_max_instances
تنظیم کرد. بین استفاده بهینه از CPUهای موجود و میزان کامپایل JIT و تعداد بازدیدهای حافظه نهان که به دست می آورید، تعادلی وجود دارد. با تعداد کارگران بیشتر، اهداف بیشتر هزینههای راهاندازی اجرای کدهای غیر JIT و ضربه زدن به حافظههای پنهان را پرداخت میکنند. اگر تعداد کمی هدف برای ساخت دارید، یک کارگر ممکن است بهترین مبادله را بین سرعت کامپایل و استفاده از منابع ارائه دهد (به عنوان مثال، شماره 8586 را ببینید. پرچم worker_max_instances
حداکثر تعداد نمونه های کارگر را در هر یادداشت و پرچم تعیین می کند. تنظیم کنید (به زیر مراجعه کنید)، بنابراین در یک سیستم ترکیبی، اگر مقدار پیشفرض را حفظ کنید، میتوانید از حافظه بسیار زیادی استفاده کنید.
این نمودار زمانهای جمعآوری از ابتدا برای Bazel (هدف //src:bazel
) را روی یک ایستگاه کاری لینوکس 3.5 گیگاهرتزی Intel Xeon با 64 گیگابایت رم با بیشتردد 6 هستهای نشان میدهد. برای هر پیکربندی کارگر، پنج ساخت تمیز اجرا می شود و میانگین چهار مورد آخر گرفته می شود.
شکل 1. نمودار بهبود عملکرد ساختمان های تمیز.
برای این پیکربندی، دو کارگر سریعترین کامپایل را ارائه میدهند، هرچند در مقایسه با یک کارگر تنها 14 درصد بهبود دارند. اگر می خواهید از حافظه کمتری استفاده کنید، One Worker گزینه خوبی است.
کامپایل افزایشی معمولاً مزایای بیشتری دارد. ساختهای تمیز نسبتاً نادر هستند، اما تغییر یک فایل بین کامپایلها، بهویژه در توسعه مبتنی بر آزمایش، رایج است. مثال بالا همچنین دارای برخی اقدامات بسته بندی غیر جاوا است که می تواند زمان کامپایل افزایشی را تحت الشعاع قرار دهد.
کامپایل مجدد فقط منابع جاوا ( //src/main/java/com/google/devtools/build/lib/bazel:BazelServer_deploy.jar
) پس از تغییر یک ثابت رشته داخلی در AbstractContainerizingSandboxedSpawn.java سرعت 3 برابری (میانگین 20) می دهد. ساختهای افزایشی با حذف یک ساخت گرمآپ):
شکل 2. نمودار بهبود عملکرد ساخت های افزایشی.
افزایش سرعت بستگی به تغییر ایجاد شده دارد. سرعت یک ضریب 6 در شرایط فوق زمانی که یک ثابت رایج مورد استفاده تغییر می کند اندازه گیری می شود.
اصلاح کارگران مداوم
میتوانید پرچم --worker_extra_flag
را برای مشخص کردن پرچمهای راهاندازی به کارگران، که توسط یادداشت کلید زده میشوند، ارسال کنید. به عنوان مثال، ارسال --worker_extra_flag=javac=--debug
، اشکال زدایی را فقط برای Javac روشن می کند. تنها یک پرچم کارگر را می توان در هر استفاده از این پرچم تنظیم کرد و فقط برای یک یادگاری. کارگران نه تنها به طور جداگانه برای هر یادگاری ایجاد می شوند، بلکه برای تغییرات در پرچم های راه اندازی آنها نیز ایجاد می شوند. هر ترکیبی از پرچمهای یادگاری و راهاندازی در یک WorkerKey
ترکیب میشود و برای هر WorkerKey
تا worker_max_instances
ممکن است کارگران ایجاد شوند. بخش بعدی را ببینید که چگونه پیکربندی کنش میتواند پرچمهای راهاندازی را نیز مشخص کند.
شما میتوانید از پرچم --high_priority_workers
برای تعیین یک یادگاری استفاده کنید که باید در اولویت اجرای حافظههای با اولویت عادی باشد. این می تواند به اولویت بندی اقداماتی که همیشه در مسیر بحرانی هستند کمک کند. اگر دو یا چند کارگر با اولویت بالا درخواستها را اجرا میکنند، از اجرای همه کارگران دیگر جلوگیری میشود. این پرچم را می توان چندین بار استفاده کرد.
ارسال پرچم --worker_sandboxing
باعث می شود که هر درخواست کارگر از یک پوشه سندباکس جداگانه برای همه ورودی های خود استفاده کند. راهاندازی سندباکس ، بهویژه در macOS زمان بیشتری میبرد، اما ضمانت صحت بهتری را ارائه میدهد.
پرچم --worker_quit_after_build
عمدتا برای اشکال زدایی و پروفایل مفید است. این پرچم همه کارگران را مجبور میکند پس از اتمام ساخت، کار را ترک کنند. همچنین میتوانید --worker_verbose
را برای دریافت خروجی بیشتر در مورد کاری که کارگران انجام میدهند، پاس کنید. این پرچم در قسمت پرحرفی در verbosity
منعکس میشود و به پیادهسازیهای کارگر اجازه WorkRequest
باشند.
کارگران گزارش های خود را در فهرست <outputBase>/bazel-workers
ذخیره می کنند، به عنوان مثال /tmp/_bazel_larsrc/191013354bebe14fdddae77f2679c3ef/bazel-workers/worker-1-Javac.log
. نام فایل شامل شناسه کارگر و یادگاری است. از آنجایی که میتواند بیش از یک WorkerKey
در هر یادگاری وجود داشته باشد، ممکن است بیش از worker_max_instances
فایلهای گزارش برای یک یادگاری معین مشاهده کنید.
برای ساختهای اندروید، جزئیات را در صفحه عملکرد ساخت اندروید ببینید .
پیاده سازی کارگران مستمر
برای اطلاعات بیشتر در مورد نحوه ایجاد یک کارگر، صفحه ایجاد کارگران پایدار را ببینید.
این مثال یک پیکربندی Starlark را برای کارگری که از JSON استفاده می کند نشان می دهد:
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
به شکل زیر خواهد بود:
توجه: در حالی که مشخصات بافر پروتکل از "snake case" ( request_id
) استفاده می کند، پروتکل JSON از "camel case" ( requestId
) استفاده می کند. در این سند، در نمونههای JSON از casel case استفاده میکنیم، اما از snake case بدون در نظر گرفتن پروتکل، در مورد زمینه صحبت میکنیم.
{
"arguments": [ "-g", "-source", "1.5", "Foo.java" ]
"inputs": [
{ "path": "symlinkfarm/input1", "digest": "d49a..." },
{ "path": "symlinkfarm/input2", "digest": "093d..." },
],
}
کارگر این را در stdin
در قالب JSON محدود شده با خط جدید دریافت می کند (زیرا requires-worker-protocol
روی JSON تنظیم شده است). سپس کارگر این عمل را انجام می دهد و یک WorkResponse با فرمت JSON به WorkResponse
در stdout خود ارسال می کند. سپس 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 ، میتوانید نمونهای از wrapperهای کارگر نوشته شده در جاوا و همچنین در پایتون را ببینید. اگر در جاوا اسکریپت یا تایپ اسکریپت کار می کنید، بسته @bazel/worker و مثال کارگر nodejs ممکن است مفید باشد.
کارگران چگونه بر سندباکس تاثیر می گذارند؟
استفاده از استراتژی worker
به طور پیشفرض، عملکرد را در جعبه ایمنی اجرا نمیکند، مشابه استراتژی local
. میتوانید پرچم --worker_sandboxing
را طوری تنظیم کنید که همه کارگران داخل جعبههای ایمنی اجرا شوند، مطمئن شوید که هر اجرای ابزار فقط فایلهای ورودی را میبیند که قرار است داشته باشد. این ابزار همچنان ممکن است اطلاعات بین درخواستها را به صورت داخلی نشت کند، به عنوان مثال از طریق یک حافظه پنهان. استفاده از استراتژی dynamic
مستلزم آن است که کارگران جعبهشنی شوند .
برای اجازه استفاده صحیح از کش های کامپایلر با کارگران، یک خلاصه به همراه هر فایل ورودی ارسال می شود. بنابراین کامپایلر یا بسته بندی می توانند بدون نیاز به خواندن فایل بررسی کنند که آیا ورودی هنوز معتبر است یا خیر.
حتی زمانی که از هضمهای ورودی برای محافظت در برابر ذخیرهسازی ناخواسته استفاده میکنید، کارگران sandboxed جعبهشنی ماسهبازی سختتری را نسبت به جعبههای ماسهبازی خالص ارائه میکنند، زیرا این ابزار ممکن است حالت داخلی دیگری را که تحت تأثیر درخواستهای قبلی قرار گرفته است، حفظ کند.
کارگران Multiplex تنها در صورتی میتوانند سندباکس شوند که پیادهسازی کارگر از آن پشتیبانی کند، و این sandboxing باید به طور جداگانه با پرچم --experimental_worker_multiplex_sandboxing
فعال شود. جزئیات بیشتر را در سند طراحی مشاهده کنید).
بیشتر خواندن
برای کسب اطلاعات بیشتر در مورد کارگران دائمی، نگاه کنید به:
- پست اصلی وبلاگ کارگران مداوم
- شرح پیاده سازی Haskell {: .external}
- پست وبلاگ توسط Mike Morearty {: .external}
- توسعه Front End با Bazel: Angular/TypeScript and Persistent Workers w/ Asana {: .external}
- استراتژی های بازل توضیح داده شد {: .external}
- بحث استراتژی آموزنده کارگر در لیست پستی bazel-discuss {: .external}