کارگران پیگیر

این صفحه نحوه استفاده از کارگران مداوم، مزایا، الزامات و نحوه تأثیر کارگران بر سندباکس را پوشش می دهد.

یک کارگر دائمی یک فرآیند طولانی مدت است که توسط سرور 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 هسته‌ای نشان می‌دهد. برای هر پیکربندی کارگر، پنج ساخت تمیز اجرا می شود و میانگین چهار مورد آخر گرفته می شود.

Graph of performance improvements of clean builds

شکل 1. نمودار بهبود عملکرد ساختمان های تمیز.

برای این پیکربندی، دو کارگر سریع‌ترین کامپایل را ارائه می‌دهند، هرچند در مقایسه با یک کارگر تنها 14 درصد بهبود دارند. اگر می خواهید از حافظه کمتری استفاده کنید، One Worker گزینه خوبی است.

کامپایل افزایشی معمولاً مزایای بیشتری دارد. ساخت‌های تمیز نسبتاً نادر هستند، اما تغییر یک فایل بین کامپایل‌ها، به‌ویژه در توسعه مبتنی بر آزمایش، رایج است. مثال بالا همچنین دارای برخی اقدامات بسته بندی غیر جاوا است که می تواند زمان کامپایل افزایشی را تحت الشعاع قرار دهد.

کامپایل مجدد فقط منابع جاوا ( //src/main/java/com/google/devtools/build/lib/bazel:BazelServer_deploy.jar ) پس از تغییر یک ثابت رشته داخلی در AbstractContainerizingSandboxedSpawn.java سرعت 3 برابری (میانگین 20) می دهد. ساخت‌های افزایشی با حذف یک ساخت گرم‌آپ):

Graph of performance improvements of incremental builds

شکل 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 فعال شود. جزئیات بیشتر را در سند طراحی مشاهده کنید).

بیشتر خواندن

برای کسب اطلاعات بیشتر در مورد کارگران دائمی، نگاه کنید به: