رندر WebGL روی سرور بدون GPU
خلاصهٔ کاملتر
WebGL این روزها همهجا هست؛ از نقشههای سهبعدی و پیکربندیکنندههای محصول گرفته تا لندینگهای پر از شیدر. اما به گفتهٔ نویسنده، همین صفحهها کندترین چیزی بودن که میشد از سرویس اسکرینشات میکرولینک خواست. نکتهٔ اصلی مقاله اینه که با یه تغییر تکخطی تو تنظیمات کروم، این کندی تا حد زیادی حل شد.
ماجرا از اینجا شروع میشه که سرورهای میکرولینک اصلاً کارت گرافیک ندارن؛ ارزونتر و سادهترن. ولی WebGL یه API گرافیکیه و بدون GPU باید یه چیزی روی CPU شبیهسازیش کنه. کروم خودش WebGL رو رندر نمیکنه، بلکه اونو میسپره به ANGLE که بسته به پلتفرم یه بکاند مناسب (مثل Direct3D، Metal یا یه رندرکنندهٔ نرمافزاری) انتخاب میکنه.
وقتی GPU نباشه، همهچیز به همون رندرکنندهٔ نرمافزاری برمیگرده. کروم دوتا داره: SwiftShader پیشفرض، یا استک OpenGL سیستم که روی لینوکس همون Mesa llvmpipe هست. خروجی هردو یکیه، ولی سرعتشون زمین تا آسمون فرق داره؛ یه صحنهٔ سهبعدی سنگین با SwiftShader حدود ۲۴ ثانیه و با llvmpipe حدود ۶ ثانیه رندر میشه.
نویسنده توضیح میده که این چهار برابر شدن سرعت بیدلیل نیست: llvmpipe به کمک LLVM شیدر و state رو همونجا به کد نیتیو x86-64 کامپایل میکنه و خبری از حلقهٔ مفسر نیست، ضمن اینکه tiled و چندنخیه و از همهٔ هستهها استفاده میکنه. خود تغییر هم فقط همینه:
- '--use-angle=swiftshader',
+ '--use-angle=gl',اما به گفتهٔ نویسنده همین فلگ ساده چند تا قلاب داره. اول اینکه نباید --disable-gpu رو اضافه کنی، چون بیسروصدا دوباره SwiftShader رو روشن میکنه و این پرتکرارترین فلگ تو آموزشهای headless هست. دوم اینکه --use-angle=gl برای بایندشدن به یه GL surface به یه display نیاز داره، حتی تو حالت headless؛ وگرنه WebGL بیصدا به یه fallback دوبعدی سقوط میکنه و خروجی غلط ولی بهظاهر درست تحویل میده.
برای همین هر کانتینر قبل از اجرای کروم یه display مجازی با Xvfb بالا میاره و با LIBGL_ALWAYS_SOFTWARE=1 مطمئن میشه که Mesa روی llvmpipe بمونه. چون نسخهٔ Mesa روی Ubuntu jammy برای این کار خیلی قدیمیه، خود Mesa از سورس و فقط با درایور llvmpipe کامپایل میشه و با یه Dockerfile چندمرحلهای حجم ایمیج از ۴.۵ به ۲.۶۵ گیگابایت میرسه.
نویسنده آخرش صادقانه میگه این راهحل بیشترِ فاصله رو پر میکنه، نه همهشو. صفحههای خیلی سنگین با شیدرهای fragment ممکنه هنوز سیاه دربیان، چون canvas تا لحظهٔ عکسگرفتن هنوز paint نشده؛ این یه مسابقهٔ first-paint هست، نه مشکل رندرکننده، و هیچ فلگی حلش نمیکنه.
نکات کلیدی:
- سرورهای بدون GPU برای رندر WebGL باید روی CPU شبیهسازی کنن
- سوییچ از SwiftShader به Mesa llvmpipe با فلگ --use-angle=gl سرعت رو حدود ۴ برابر کرد (از ۲۴ به ۶ ثانیه)
- اضافهکردن --disable-gpu یا --in-process-gpu مسیر سریع رو خراب میکنه
- بدون یه display مجازی مثل Xvfb، خروجی بیصدا به حالت دوبعدی سقوط میکنه
- Mesa از سورس کامپایل شده و حجم ایمیج داکر تقریباً نصف شده




