بهینهسازی هدایتشده نمایه (همچنین به عنوان PGO یا «pogo» نیز شناخته میشود) روشی برای بهینهسازی بیشتر ساختهای بهینهسازی شده بازی شما با استفاده از اطلاعاتی درباره نحوه رفتار بازی شما هنگام بازی در دنیای واقعی است. به این ترتیب، کدهایی که به ندرت اجرا می شوند، مانند خطا یا موارد لبه، از مسیرهای اجرای حیاتی کد شما حذف می شوند و سرعت آن را افزایش می دهند.
شکل 1. مروری بر نحوه عملکرد PGO.
برای استفاده از PGO، ابتدا بیلد خود را برای تولید داده های نمایه ای که کامپایلر می تواند با آن کار کند، ابزار می کنید. سپس کد خود را با اجرای آن بیلد و تولید یک یا چند فایل داده پروفایل اعمال می کنید. در نهایت، آن فایلها را از دستگاه کپی میکنید و از آنها با کامپایلر برای بهینهسازی فایل اجرایی خود با استفاده از اطلاعات نمایهای که گرفتهاید استفاده میکنید.
نحوه کار ساخت های بهینه شده بدون PGO
سازهای که بدون استفاده از دادههای نمایه بهینهسازی میشود، هنگام تصمیمگیری درباره نحوه تولید کد بهینهشده، از تعدادی اکتشافی استفاده میکند.
برخی از آنها به صراحت توسط توسعهدهنده علامتگذاری میشوند - برای مثال، در C++ 20 یا جدیدتر، با استفاده از راهنماییهای جهت شاخه مانند [[likely]]
و [[unlikely]]
. مثال دیگر استفاده از کلمه کلیدی inline
یا حتی __forceinline
خواهد بود (اگرچه به طور کلی، بهتر و انعطاف پذیرتر است که از کلمه قبلی استفاده کنید). بهطور پیشفرض، برخی از کامپایلرها فرض میکنند که اولین پایه یک شاخه (یعنی عبارت if
، نه قسمت else
) محتملترین پایه است. بهینه ساز همچنین ممکن است از تجزیه و تحلیل استاتیک کد در مورد نحوه اجرای آن مفروضاتی ایجاد کند - اما این معمولاً از نظر دامنه محدود است.
مشکل این اکتشافی ها این است که آنها نمی توانند به درستی به کامپایلر در همه موقعیت ها کمک کنند - حتی با نشانه گذاری دستی کامل - بنابراین اگرچه کد تولید شده معمولاً به خوبی بهینه شده است، اما اگر کامپایلر می توانسته باشد، خوب نیست. اطلاعات بیشتر در مورد رفتار آن در زمان اجرا.
ایجاد نمایه
هنگامی که فایل اجرایی شما با PGO فعال در حالت ابزاری ساخته می شود، فایل اجرایی شما با کد در ابتدای هر بلوک کد تقویت می شود - برای مثال، ابتدای یک تابع، یا ابتدای هر بازوی یک شاخه. این کد برای پیگیری تعداد دفعاتی که بلوک توسط کدهای در حال اجرا وارد می شود، استفاده می شود، که کامپایلر می تواند بعداً از آن برای تولید کد بهینه شده استفاده کند.
برخی ردیابیهای دیگر نیز انجام میشود - به عنوان مثال، اندازه عملیات کپی معمولی در یک بلوک، به طوری که نسخههای سریع و خطبندی شده عملیات میتواند بعداً تولید شود.
پس از انجام نوعی کار نمایندگی توسط بازی، فایل اجرایی باید تابعی – __llvm_profile_write_file()
– را فراخوانی کند تا اطلاعات نمایه را در یک مکان قابل تنظیم در دستگاه بنویسد. هنگامی که تنظیمات ساخت شما دارای ابزار دقیق PGO فعال باشد، این عملکرد به طور خودکار به بازی شما متصل می شود.
سپس فایل داده های پروفایل نوشته شده باید دوباره در رایانه میزبان کپی شود و ترجیحاً در مکانی همراه با پروفایل های دیگر از همان ساخت نگهداری شود تا بتوان با هم از آنها استفاده کرد.
به عنوان مثال، می توانید کد بازی خود را تغییر دهید تا زمانی که صحنه بازی فعلی به پایان می رسد، __llvm_profile_write_file()
را فراخوانی کنید. سپس، برای گرفتن یک نمایه، بازی خود را با ابزار دقیق روشن میسازید و سپس آن را در دستگاه اندروید خود اجرا میکنید. در حین اجرا، دادههای نمایه بهطور خودکار ضبط میشوند - مهندس QA شما در بازی اجرا میشود، سناریوهای مختلفی را انجام میدهد (یا فقط به قبولی آزمون عادی خود میپردازد).
وقتی تمرین بخشهای مختلف بازی خود را تمام کردید، میتوانید به منوی اصلی بازگردید، که صحنه فعلی بازی را به پایان میرساند و دادههای نمایه را مینویسد.
سپس می توان از یک اسکریپت برای کپی کردن داده های نمایه از دستگاه آزمایشی استفاده کرد و آن را در یک مخزن مرکزی آپلود کرد که در آنجا می توان آن را برای استفاده بعدی ضبط کرد.
ادغام داده های نمایه
هنگامی که یک نمایه از یک دستگاه به دست آمد، باید از فایل داده پروفایل تولید شده توسط ساخت ابزار دقیق، به فرمی تبدیل شود که کامپایلر بتواند آن را مصرف کند. AGDE این کار را به طور خودکار برای شما انجام می دهد، برای هر فایل داده پروفایلی که به پروژه خود اضافه می کنید.
PGO برای ترکیب نتایج اجرای چندین نمایه ابزاردار با هم طراحی شده است - اگر چندین فایل در یک پروژه واحد دارید، AGDE این کار را به طور خودکار برای شما انجام می دهد.
به عنوان مثالی از اینکه چگونه ادغام مجموعه داده های پروفایل می تواند مفید باشد، فرض کنید که شما یک آزمایشگاه پر از مهندسان QA داشتید که همگی سطوح مختلف بازی شما را انجام می دادند. هر یک از بازیهای آنها ضبط میشود و سپس برای تولید دادههای نمایه از یک ساخت بازی شما با ابزار PGO استفاده میشود. ادغام پروفایل ها به شما امکان می دهد نتایج حاصل از تمام این آزمایش های مختلف را ترکیب کنید - که ممکن است بخش های مختلفی از کد شما را اجرا کنند - تا نتایج بهتری به دست آورید.
حتی بهتر از آن، هنگام انجام آزمایشهای طولی، که در آن کپیهایی از دادههای نمایه را از نسخه داخلی تا نسخه داخلی نگهداری میکنید، بازسازی لزوماً دادههای نمایه قدیمی را باطل نمیکند. در بیشتر موارد، کد از انتشار تا انتشار نسبتاً پایدار است، بنابراین دادههای نمایه از بیلدهای قدیمیتر همچنان میتوانند مفید باشند و فوراً کهنه نمیشوند.
تولید بیلدهای بهینه شده با هدایت نمایه
هنگامی که داده های نمایه را به پروژه خود اضافه کردید، می توانید با فعال کردن PGO در حالت Optimization در پیکربندی ساخت، از آن برای ساخت فایل اجرایی خود استفاده کنید.
این امر بهینه ساز کامپایلر را هدایت می کند تا هنگام تصمیم گیری بهینه سازی از داده های نمایه ای که قبلاً گرفته اید استفاده کند.
زمان استفاده از Profile-Guided Optimization
PGO قرار نیست چیزی باشد که در ابتدای توسعه یا در طول تکرار روزانه روی کد فعال میکنید. در طول توسعه، باید روی بهینهسازیهای الگوریتمی و مبتنی بر طرحبندی داده تمرکز کنید، زیرا آنها مزایای بسیار بیشتری به شما خواهند داد.
PGO بعداً در فرآیند توسعه، زمانی که در حال پرداخت برای انتشار هستید، می آید. بهینه سازی هدایت شده از نمایه را به عنوان ابزاری در بالای صفحه در نظر بگیرید که به شما امکان می دهد پس از اینکه خودتان مدتی را صرف بهینه سازی کد خود کرده اید، آخرین بیت از عملکرد را از کد خود حذف کنید.
بهبود عملکرد مورد انتظار با PGO
این به عوامل زیادی بستگی دارد، از جمله اینکه نمایههای شما چقدر جامع و قدیمی هستند، و اینکه کد شما با ساخت بهینهسازی سنتی چقدر به بهینه نزدیک میشد.
به طور کلی، یک تخمین بسیار محافظه کارانه می تواند این باشد که هزینه های CPU تا 5٪ در موضوعات کلیدی کاهش می یابد. ممکن است نتایج متفاوتی ببینید.
سربار ابزار دقیق
ابزار دقیق PGO جامع است، و در حالی که به طور خودکار تولید می شود، رایگان نیست. هزینه سربار ابزار دقیق PGO ممکن است بسته به پایگاه کد شما متفاوت باشد.
هزینه عملکرد ابزار دقیق هدایت شده توسط نمایه
ممکن است با ساختهای ابزاردار شاهد کاهش نرخ فریم باشید. در برخی موارد - بسته به میزان استفاده از CPU شما در طول عملکرد عادی به 100٪ - ممکن است این افت آنقدر زیاد باشد که گیم پلی عادی را دشوار کند.
ما توصیه می کنیم که اکثر توسعه دهندگان یک حالت پخش نیمه قطعی برای بازی خود بسازند. این نوع عملکرد به تیم QA شما این امکان را می دهد که بازی را در یک مکان شروع شناخته شده و قابل تکرار در بازی شما (مانند یک بازی ذخیره یا سطح تست خاص) شروع کند و سپس ورودی خود را ثبت کند. این ورودی ضبط شده از ساخت آزمایشی را می توان به یک ساخت PGO-Instrumented وارد کرد، پخش کرد و داده های نمایه دنیای واقعی را بدون توجه به مدت زمانی که برای پردازش یک فریم نیاز دارد تولید کرد - حتی اگر بازی آنقدر آهسته اجرا شود که غیر قابل پخش
این نوع عملکرد مزایای عمده دیگری نیز دارد، مانند افزایش تلاش تستر: یک تستر میتواند ورودی خود را روی یک دستگاه ضبط کند، و سپس میتواند در چندین نوع مختلف دستگاه برای اهداف تست دود پخش شود.
سیستم پخش مجدد مانند این می تواند مزایای زیادی در Android داشته باشد، جایی که تعداد زیادی از انواع دستگاه ها در اکوسیستم وجود دارد - و مزایا به همین جا ختم نمی شود: می تواند بخش اصلی سیستم ساخت یکپارچه سازی مداوم شما را نیز تشکیل دهد و به شما امکان می دهد آزمایشات رگرسیون عملکرد و دود به طور منظم یک شبه را انجام دهید.
ضبط باید ورودی کاربر را در مناسب ترین نقطه در مکانیزم ورودی بازی شما ثبت کند (احتمالاً رویدادهای صفحه لمسی مستقیم نیست، بلکه پیامدهای آنها را به عنوان دستور ضبط می کند). این ورودیها همچنین باید دارای تعداد فریمهایی باشند که در طول گیمپلی بهطور یکنواخت افزایش مییابد، به طوری که در حین پخش، مکانیسم پخش مجدد میتواند منتظر فریم مناسبی باشد که روی آن باید یک رویداد را آغاز کند.
در حالت پخش، بازی شما باید از ورود آنلاین اجتناب کند، نباید تبلیغات را نشان دهد و باید در یک مرحله زمانی ثابت (با نرخ فریم هدف شما) کار کند. شما باید vsync را غیرفعال کنید.
مهم نیست که همه چیز (به عنوان مثال، سیستم های ذرات) در بازی شما کاملاً قطعی قابل تکرار باشد، اما اقدامات یکسان باید نتایج و نتایج یکسانی را در بازی ارائه دهند - یعنی گیم پلی باید یکسان باشد.
هزینه حافظه ابزار دقیق هدایت شده توسط پروفایل
سربار حافظه ابزار دقیق PGO بر اساس کتابخانه خاصی که کامپایل می شود بسیار متفاوت است. در آزمایشهای خود شاهد افزایش کلی اندازه آزمون قابل اجرا به میزان 2.2 برابر بودیم. این افزایش اندازه شامل کد اضافی مورد نیاز برای ابزارسازی بلوکهای کد و فضای مورد نیاز برای ذخیره شمارندهها میشود. این تست ها جامع نبودند و تجربه شما ممکن است متفاوت باشد.
چه زمانی دادههای نمایهتان را بهروزرسانی یا کنار بگذارید
هر زمان که تغییر زیادی در کد (یا محتوای بازی) خود ایجاد کردید، باید پروفایل های خود را به روز کنید.
این دقیقاً به محیط ساخت شما و جایی که در حال توسعه هستید بستگی دارد.
همانطور که قبلا ذکر شد، شما نباید داده های نمایه را در میان تغییرات عمده محیط ساخت حمل کنید. در حالی که این شما را از ساختن یا شکستن ساختنتان باز نمیدارد، اما مزایای عملکرد استفاده از PGO را کاهش میدهد، زیرا دادههای نمایه بسیار کمی برای محیط ساخت جدید قابل اعمال خواهد بود. با این حال، این تنها موردی نیست که ممکن است اطلاعات نمایه شما کهنه شود.
بیایید با این فرض شروع کنیم که از PGO تا پایان توسعه و زمانی که در حال آماده شدن برای انتشار هستید استفاده نخواهید کرد، فراتر از جمعآوری یک عکس هفتگی به طوری که مهندسان متمرکز بر عملکرد بتوانند تأیید کنند که هیچ مشکل غیرمنتظرهای وجود نخواهد داشت. نزدیکتر به انتشار
با نزدیک شدن به پنجره انتشار خود، زمانی که تیم QA شما هر روز در حال آزمایش است و به طور کامل بازی را اجرا می کند، این تغییر می کند. در طول این مرحله میتوانید پروفایلهایی را روزانه از آن دادهها تولید کنید و از آنها برای اطلاعرسانی به ساختهای آینده برای آزمایش عملکرد و تنظیم بودجه عملکرد خود استفاده کنید.
هنگامی که برای انتشار آماده میشوید، باید نسخه ساختی را که قصد انتشار آن را دارید قفل کنید و سپس QA را از طریق آن اجرا کنید تا دادههای نمایه جدید شما تولید شود. سپس با استفاده از این داده ها می سازید تا نسخه نهایی فایل اجرایی خود را تولید کنید.
پس از آن QA می تواند به این ساخت حمل و نقل بهینه سازی شده، یک مرحله نهایی را ارائه دهد تا اطمینان حاصل شود که انتشار آن خوب است.
،بهینهسازی هدایتشده نمایه (همچنین به عنوان PGO یا «pogo» نیز شناخته میشود) روشی برای بهینهسازی بیشتر ساختهای بهینهسازی شده بازی شما با استفاده از اطلاعاتی درباره نحوه رفتار بازی شما هنگام بازی در دنیای واقعی است. به این ترتیب، کدهایی که به ندرت اجرا می شوند، مانند خطا یا موارد لبه، از مسیرهای اجرای حیاتی کد شما حذف می شوند و سرعت آن را افزایش می دهند.
شکل 1. مروری بر نحوه عملکرد PGO.
برای استفاده از PGO، ابتدا بیلد خود را برای تولید داده های نمایه ای که کامپایلر می تواند با آن کار کند، ابزار می کنید. سپس کد خود را با اجرای آن بیلد و تولید یک یا چند فایل داده پروفایل اعمال می کنید. در نهایت، آن فایلها را از دستگاه کپی میکنید و از آنها با کامپایلر برای بهینهسازی فایل اجرایی خود با استفاده از اطلاعات نمایهای که گرفتهاید استفاده میکنید.
نحوه کار ساخت های بهینه شده بدون PGO
سازهای که بدون استفاده از دادههای نمایه بهینهسازی میشود، هنگام تصمیمگیری درباره نحوه تولید کد بهینهشده، از تعدادی اکتشافی استفاده میکند.
برخی از آنها به صراحت توسط توسعهدهنده علامتگذاری میشوند - برای مثال، در C++ 20 یا جدیدتر، با استفاده از راهنماییهای جهت شاخه مانند [[likely]]
و [[unlikely]]
. مثال دیگر استفاده از کلمه کلیدی inline
یا حتی __forceinline
خواهد بود (اگرچه به طور کلی، بهتر و انعطاف پذیرتر است که از کلمه قبلی استفاده کنید). بهطور پیشفرض، برخی از کامپایلرها فرض میکنند که اولین پایه یک شاخه (یعنی عبارت if
، نه قسمت else
) محتملترین پایه است. بهینه ساز همچنین ممکن است از تجزیه و تحلیل استاتیک کد در مورد نحوه اجرای آن مفروضاتی ایجاد کند - اما این معمولاً از نظر دامنه محدود است.
مشکل این اکتشافی ها این است که آنها نمی توانند به درستی به کامپایلر در همه موقعیت ها کمک کنند - حتی با نشانه گذاری دستی کامل - بنابراین اگرچه کد تولید شده معمولاً به خوبی بهینه شده است، اما اگر کامپایلر می توانسته باشد، خوب نیست. اطلاعات بیشتر در مورد رفتار آن در زمان اجرا.
ایجاد نمایه
هنگامی که فایل اجرایی شما با PGO فعال در حالت ابزاری ساخته می شود، فایل اجرایی شما با کد در ابتدای هر بلوک کد تقویت می شود - برای مثال، ابتدای یک تابع، یا ابتدای هر بازوی یک شاخه. این کد برای پیگیری تعداد دفعاتی که بلوک توسط کدهای در حال اجرا وارد می شود، استفاده می شود، که کامپایلر می تواند بعداً از آن برای تولید کد بهینه شده استفاده کند.
برخی ردیابیهای دیگر نیز انجام میشود - به عنوان مثال، اندازه عملیات کپی معمولی در یک بلوک، به طوری که نسخههای سریع و خطبندی شده عملیات میتواند بعداً تولید شود.
پس از انجام نوعی کار نمایندگی توسط بازی، فایل اجرایی باید تابعی – __llvm_profile_write_file()
– را فراخوانی کند تا اطلاعات نمایه را در یک مکان قابل تنظیم در دستگاه بنویسد. هنگامی که تنظیمات ساخت شما دارای ابزار دقیق PGO فعال باشد، این عملکرد به طور خودکار به بازی شما متصل می شود.
سپس فایل داده های پروفایل نوشته شده باید دوباره در رایانه میزبان کپی شود و ترجیحاً در مکانی همراه با پروفایل های دیگر از همان ساخت نگهداری شود تا بتوان با هم از آنها استفاده کرد.
به عنوان مثال، می توانید کد بازی خود را تغییر دهید تا زمانی که صحنه بازی فعلی به پایان می رسد، __llvm_profile_write_file()
را فراخوانی کنید. سپس، برای گرفتن یک نمایه، بازی خود را با ابزار دقیق روشن میسازید و سپس آن را در دستگاه اندروید خود اجرا میکنید. در حین اجرا، دادههای نمایه بهطور خودکار ضبط میشوند - مهندس QA شما در بازی اجرا میشود، سناریوهای مختلفی را انجام میدهد (یا فقط به قبولی آزمون عادی خود میپردازد).
وقتی تمرین بخشهای مختلف بازی خود را تمام کردید، میتوانید به منوی اصلی بازگردید، که صحنه فعلی بازی را به پایان میرساند و دادههای نمایه را مینویسد.
سپس می توان از یک اسکریپت برای کپی کردن داده های نمایه از دستگاه آزمایشی استفاده کرد و آن را در یک مخزن مرکزی آپلود کرد که در آنجا می توان آن را برای استفاده بعدی ضبط کرد.
ادغام داده های نمایه
هنگامی که یک نمایه از یک دستگاه به دست آمد، باید از فایل داده پروفایل تولید شده توسط ساخت ابزار دقیق، به فرمی تبدیل شود که کامپایلر بتواند آن را مصرف کند. AGDE این کار را به طور خودکار برای شما انجام می دهد، برای هر فایل داده پروفایلی که به پروژه خود اضافه می کنید.
PGO برای ترکیب نتایج اجرای چندین نمایه ابزاردار با هم طراحی شده است - اگر چندین فایل در یک پروژه واحد دارید، AGDE این کار را به طور خودکار برای شما انجام می دهد.
به عنوان مثالی از اینکه چگونه ادغام مجموعه داده های پروفایل می تواند مفید باشد، فرض کنید که شما یک آزمایشگاه پر از مهندسان QA داشتید که همگی سطوح مختلف بازی شما را انجام می دادند. هر یک از بازیهای آنها ضبط میشود و سپس برای تولید دادههای نمایه از یک ساخت بازی شما با ابزار PGO استفاده میشود. ادغام پروفایل ها به شما امکان می دهد نتایج حاصل از تمام این آزمایش های مختلف را ترکیب کنید - که ممکن است بخش های مختلفی از کد شما را اجرا کنند - تا نتایج بهتری به دست آورید.
حتی بهتر از آن، هنگام انجام آزمایشهای طولی، که در آن کپیهایی از دادههای نمایه را از نسخه داخلی تا نسخه داخلی نگهداری میکنید، بازسازی لزوماً دادههای نمایه قدیمی را باطل نمیکند. در بیشتر موارد، کد از انتشار تا انتشار نسبتاً پایدار است، بنابراین دادههای نمایه از بیلدهای قدیمیتر همچنان میتوانند مفید باشند و فوراً کهنه نمیشوند.
تولید بیلدهای بهینه شده با هدایت نمایه
هنگامی که داده های نمایه را به پروژه خود اضافه کردید، می توانید با فعال کردن PGO در حالت Optimization در پیکربندی ساخت، از آن برای ساخت فایل اجرایی خود استفاده کنید.
این امر بهینه ساز کامپایلر را هدایت می کند تا هنگام تصمیم گیری بهینه سازی از داده های نمایه ای که قبلاً گرفته اید استفاده کند.
زمان استفاده از Profile-Guided Optimization
PGO قرار نیست چیزی باشد که در ابتدای توسعه یا در طول تکرار روزانه روی کد فعال میکنید. در طول توسعه، باید روی بهینهسازیهای الگوریتمی و مبتنی بر طرحبندی داده تمرکز کنید، زیرا آنها مزایای بسیار بیشتری به شما خواهند داد.
PGO بعداً در فرآیند توسعه، زمانی که در حال پرداخت برای انتشار هستید، می آید. بهینه سازی هدایت شده از نمایه را به عنوان ابزاری در بالای صفحه در نظر بگیرید که به شما امکان می دهد پس از اینکه خودتان مدتی را صرف بهینه سازی کد خود کرده اید، آخرین بیت از عملکرد را از کد خود حذف کنید.
بهبود عملکرد مورد انتظار با PGO
این به عوامل زیادی بستگی دارد، از جمله اینکه نمایههای شما چقدر جامع و قدیمی هستند، و اینکه کد شما با ساخت بهینهسازی سنتی چقدر به بهینه نزدیک میشد.
به طور کلی، یک تخمین بسیار محافظه کارانه می تواند این باشد که هزینه های CPU تا 5٪ در موضوعات کلیدی کاهش می یابد. ممکن است نتایج متفاوتی ببینید.
سربار ابزار دقیق
ابزار دقیق PGO جامع است، و در حالی که به طور خودکار تولید می شود، رایگان نیست. هزینه سربار ابزار دقیق PGO ممکن است بسته به پایگاه کد شما متفاوت باشد.
هزینه عملکرد ابزار دقیق هدایت شده توسط نمایه
ممکن است با ساختهای ابزاردار شاهد کاهش نرخ فریم باشید. در برخی موارد - بسته به میزان استفاده از CPU شما در طول عملکرد عادی به 100٪ - ممکن است این افت آنقدر زیاد باشد که گیم پلی عادی را دشوار کند.
ما توصیه می کنیم که اکثر توسعه دهندگان یک حالت پخش نیمه قطعی برای بازی خود بسازند. این نوع عملکرد به تیم QA شما این امکان را می دهد که بازی را در یک مکان شروع شناخته شده و قابل تکرار در بازی شما (مانند یک بازی ذخیره یا سطح تست خاص) شروع کند و سپس ورودی خود را ثبت کند. این ورودی ضبط شده از ساخت آزمایشی را می توان به یک ساخت PGO-Instrumented وارد کرد، پخش کرد و داده های نمایه دنیای واقعی را بدون توجه به مدت زمانی که برای پردازش یک فریم نیاز دارد تولید کرد - حتی اگر بازی آنقدر آهسته اجرا شود که غیر قابل پخش
این نوع عملکرد مزایای عمده دیگری نیز دارد، مانند افزایش تلاش تستر: یک تستر میتواند ورودی خود را روی یک دستگاه ضبط کند، و سپس میتواند در چندین نوع مختلف دستگاه برای اهداف تست دود پخش شود.
سیستم پخش مجدد مانند این می تواند مزایای زیادی در Android داشته باشد، جایی که تعداد زیادی از انواع دستگاه ها در اکوسیستم وجود دارد - و مزایا به همین جا ختم نمی شود: می تواند بخش اصلی سیستم ساخت یکپارچه سازی مداوم شما را نیز تشکیل دهد و به شما امکان می دهد آزمایشات رگرسیون عملکرد و دود به طور منظم یک شبه را انجام دهید.
ضبط باید ورودی کاربر را در مناسب ترین نقطه در مکانیزم ورودی بازی شما ثبت کند (احتمالاً رویدادهای صفحه لمسی مستقیم نیست، بلکه پیامدهای آنها را به عنوان دستور ضبط می کند). این ورودیها همچنین باید دارای تعداد فریمهایی باشند که در طول گیمپلی بهطور یکنواخت افزایش مییابد، به طوری که در حین پخش، مکانیسم پخش مجدد میتواند منتظر فریم مناسبی باشد که روی آن باید یک رویداد را آغاز کند.
در حالت پخش، بازی شما باید از ورود آنلاین اجتناب کند، نباید تبلیغات را نشان دهد و باید در یک مرحله زمانی ثابت (با نرخ فریم هدف شما) کار کند. شما باید vsync را غیرفعال کنید.
مهم نیست که همه چیز (به عنوان مثال، سیستم های ذرات) در بازی شما کاملاً قطعی قابل تکرار باشد، اما اقدامات یکسان باید نتایج و نتایج یکسانی را در بازی ارائه دهند - یعنی گیم پلی باید یکسان باشد.
هزینه حافظه ابزار دقیق هدایت شده توسط پروفایل
سربار حافظه ابزار دقیق PGO بر اساس کتابخانه خاصی که کامپایل می شود بسیار متفاوت است. در آزمایشهای خود شاهد افزایش کلی اندازه آزمون قابل اجرا به میزان 2.2 برابر بودیم. این افزایش اندازه شامل کد اضافی مورد نیاز برای ابزارسازی بلوکهای کد و فضای مورد نیاز برای ذخیره شمارندهها میشود. این تست ها جامع نبودند و تجربه شما ممکن است متفاوت باشد.
چه زمانی دادههای نمایهتان را بهروزرسانی یا کنار بگذارید
هر زمان که تغییر زیادی در کد (یا محتوای بازی) خود ایجاد کردید، باید پروفایل های خود را به روز کنید.
این دقیقاً به محیط ساخت شما و جایی که در حال توسعه هستید بستگی دارد.
همانطور که قبلا ذکر شد، شما نباید داده های نمایه را در میان تغییرات عمده محیط ساخت حمل کنید. در حالی که این شما را از ساختن یا شکستن ساختنتان باز نمیدارد، اما مزایای عملکرد استفاده از PGO را کاهش میدهد، زیرا دادههای نمایه بسیار کمی برای محیط ساخت جدید قابل اعمال خواهد بود. با این حال، این تنها موردی نیست که ممکن است اطلاعات نمایه شما کهنه شود.
بیایید با این فرض شروع کنیم که از PGO تا پایان توسعه و زمانی که در حال آماده شدن برای انتشار هستید استفاده نخواهید کرد، فراتر از جمعآوری یک عکس هفتگی به طوری که مهندسان متمرکز بر عملکرد بتوانند تأیید کنند که هیچ مشکل غیرمنتظرهای وجود نخواهد داشت. نزدیکتر به انتشار
با نزدیک شدن به پنجره انتشار خود، زمانی که تیم QA شما هر روز در حال آزمایش است و به طور کامل بازی را اجرا می کند، این تغییر می کند. در طول این مرحله میتوانید پروفایلهایی را روزانه از آن دادهها تولید کنید و از آنها برای اطلاعرسانی به ساختهای آینده برای آزمایش عملکرد و تنظیم بودجه عملکرد خود استفاده کنید.
هنگامی که برای انتشار آماده میشوید، باید نسخه ساختی را که قصد انتشار آن را دارید قفل کنید و سپس QA را از طریق آن اجرا کنید تا دادههای نمایه جدید شما تولید شود. سپس با استفاده از این داده ها می سازید تا نسخه نهایی فایل اجرایی خود را تولید کنید.
پس از آن QA می تواند به این ساخت حمل و نقل بهینه سازی شده، یک مرحله نهایی را ارائه دهد تا اطمینان حاصل شود که انتشار آن خوب است.
،بهینهسازی هدایتشده نمایه (همچنین به عنوان PGO یا «pogo» نیز شناخته میشود) روشی برای بهینهسازی بیشتر ساختهای بهینهسازی شده بازی شما با استفاده از اطلاعاتی درباره نحوه رفتار بازی شما هنگام بازی در دنیای واقعی است. به این ترتیب، کدهایی که به ندرت اجرا می شوند، مانند خطا یا موارد لبه، از مسیرهای اجرای حیاتی کد شما حذف می شوند و سرعت آن را افزایش می دهند.
شکل 1. مروری بر نحوه عملکرد PGO.
برای استفاده از PGO، ابتدا بیلد خود را برای تولید داده های نمایه ای که کامپایلر می تواند با آن کار کند، ابزار می کنید. سپس کد خود را با اجرای آن بیلد و تولید یک یا چند فایل داده پروفایل اعمال می کنید. در نهایت، آن فایلها را از دستگاه کپی میکنید و از آنها با کامپایلر برای بهینهسازی فایل اجرایی خود با استفاده از اطلاعات نمایهای که گرفتهاید استفاده میکنید.
نحوه کار ساخت های بهینه شده بدون PGO
سازهای که بدون استفاده از دادههای نمایه بهینهسازی میشود، هنگام تصمیمگیری درباره نحوه تولید کد بهینهشده، از تعدادی اکتشافی استفاده میکند.
برخی از آنها به صراحت توسط توسعهدهنده علامتگذاری میشوند - برای مثال، در C++ 20 یا جدیدتر، با استفاده از راهنماییهای جهت شاخه مانند [[likely]]
و [[unlikely]]
. مثال دیگر استفاده از کلمه کلیدی inline
یا حتی __forceinline
خواهد بود (اگرچه به طور کلی، بهتر و انعطاف پذیرتر است که از کلمه قبلی استفاده کنید). بهطور پیشفرض، برخی از کامپایلرها فرض میکنند که اولین پایه یک شاخه (یعنی عبارت if
، نه قسمت else
) محتملترین پایه است. بهینه ساز همچنین ممکن است از تجزیه و تحلیل استاتیک کد در مورد نحوه اجرای آن مفروضاتی ایجاد کند - اما این معمولاً از نظر دامنه محدود است.
مشکل این اکتشافی ها این است که آنها نمی توانند به درستی به کامپایلر در همه موقعیت ها کمک کنند - حتی با نشانه گذاری دستی کامل - بنابراین اگرچه کد تولید شده معمولاً به خوبی بهینه شده است، اما اگر کامپایلر می توانسته باشد، خوب نیست. اطلاعات بیشتر در مورد رفتار آن در زمان اجرا.
ایجاد نمایه
هنگامی که فایل اجرایی شما با PGO فعال در حالت ابزاری ساخته می شود، فایل اجرایی شما با کد در ابتدای هر بلوک کد تقویت می شود - برای مثال، ابتدای یک تابع، یا ابتدای هر بازوی یک شاخه. این کد برای پیگیری تعداد دفعاتی که بلوک توسط کدهای در حال اجرا وارد می شود، استفاده می شود، که کامپایلر می تواند بعداً از آن برای تولید کد بهینه شده استفاده کند.
برخی ردیابیهای دیگر نیز انجام میشود - به عنوان مثال، اندازه عملیات کپی معمولی در یک بلوک، به طوری که نسخههای سریع و خطبندی شده عملیات میتواند بعداً تولید شود.
پس از انجام نوعی کار نمایندگی توسط بازی، فایل اجرایی باید تابعی – __llvm_profile_write_file()
– را فراخوانی کند تا اطلاعات نمایه را در یک مکان قابل تنظیم در دستگاه بنویسد. هنگامی که تنظیمات ساخت شما دارای ابزار دقیق PGO فعال باشد، این عملکرد به طور خودکار به بازی شما متصل می شود.
سپس فایل داده های پروفایل نوشته شده باید دوباره در رایانه میزبان کپی شود و ترجیحاً در مکانی همراه با پروفایل های دیگر از همان ساخت نگهداری شود تا بتوان با هم از آنها استفاده کرد.
به عنوان مثال، می توانید کد بازی خود را تغییر دهید تا زمانی که صحنه بازی فعلی به پایان می رسد، __llvm_profile_write_file()
را فراخوانی کنید. سپس، برای گرفتن یک نمایه، بازی خود را با ابزار دقیق روشن میسازید و سپس آن را در دستگاه اندروید خود اجرا میکنید. در حین اجرا، دادههای نمایه بهطور خودکار ضبط میشوند - مهندس QA شما در بازی اجرا میشود، سناریوهای مختلفی را انجام میدهد (یا فقط به قبولی آزمون عادی خود میپردازد).
وقتی تمرین بخشهای مختلف بازی خود را تمام کردید، میتوانید به منوی اصلی بازگردید، که صحنه فعلی بازی را به پایان میرساند و دادههای نمایه را مینویسد.
سپس می توان از یک اسکریپت برای کپی کردن داده های نمایه از دستگاه آزمایشی استفاده کرد و آن را در یک مخزن مرکزی آپلود کرد که در آنجا می توان آن را برای استفاده بعدی ضبط کرد.
ادغام داده های نمایه
هنگامی که یک نمایه از یک دستگاه به دست آمد، باید از فایل داده پروفایل تولید شده توسط ساخت ابزار دقیق، به فرمی تبدیل شود که کامپایلر بتواند آن را مصرف کند. AGDE این کار را به طور خودکار برای شما انجام می دهد، برای هر فایل داده پروفایلی که به پروژه خود اضافه می کنید.
PGO برای ترکیب نتایج اجرای چندین نمایه ابزاردار با هم طراحی شده است - اگر چندین فایل در یک پروژه واحد دارید، AGDE این کار را به طور خودکار برای شما انجام می دهد.
به عنوان مثالی از اینکه چگونه ادغام مجموعه داده های پروفایل می تواند مفید باشد، فرض کنید که شما یک آزمایشگاه پر از مهندسان QA داشتید که همگی سطوح مختلف بازی شما را انجام می دادند. هر یک از بازیهای آنها ضبط میشود و سپس برای تولید دادههای نمایه از یک ساخت بازی شما با ابزار PGO استفاده میشود. ادغام پروفایل ها به شما امکان می دهد نتایج حاصل از تمام این آزمایش های مختلف را ترکیب کنید - که ممکن است بخش های مختلفی از کد شما را اجرا کنند - تا نتایج بهتری به دست آورید.
حتی بهتر از آن، هنگام انجام آزمایشهای طولی، که در آن کپیهایی از دادههای نمایه را از نسخه داخلی تا نسخه داخلی نگهداری میکنید، بازسازی لزوماً دادههای نمایه قدیمی را باطل نمیکند. در بیشتر موارد، کد از انتشار تا انتشار نسبتاً پایدار است، بنابراین دادههای نمایه از بیلدهای قدیمیتر همچنان میتوانند مفید باشند و فوراً کهنه نمیشوند.
تولید بیلدهای بهینه شده با هدایت نمایه
هنگامی که داده های نمایه را به پروژه خود اضافه کردید، می توانید با فعال کردن PGO در حالت Optimization در پیکربندی ساخت، از آن برای ساخت فایل اجرایی خود استفاده کنید.
این امر بهینه ساز کامپایلر را هدایت می کند تا هنگام تصمیم گیری بهینه سازی از داده های نمایه ای که قبلاً گرفته اید استفاده کند.
زمان استفاده از Profile-Guided Optimization
PGO قرار نیست چیزی باشد که در ابتدای توسعه یا در طول تکرار روزانه روی کد فعال میکنید. در طول توسعه، باید روی بهینهسازیهای الگوریتمی و مبتنی بر طرحبندی داده تمرکز کنید، زیرا آنها مزایای بسیار بیشتری به شما خواهند داد.
PGO بعداً در فرآیند توسعه، زمانی که در حال پرداخت برای انتشار هستید، می آید. بهینه سازی هدایت شده از نمایه را به عنوان ابزاری در بالای صفحه در نظر بگیرید که به شما امکان می دهد پس از اینکه خودتان مدتی را صرف بهینه سازی کد خود کرده اید، آخرین بیت از عملکرد را از کد خود حذف کنید.
بهبود عملکرد مورد انتظار با PGO
این به عوامل زیادی بستگی دارد، از جمله اینکه نمایههای شما چقدر جامع و قدیمی هستند، و اینکه کد شما با ساخت بهینهسازی سنتی چقدر به بهینه نزدیک میشد.
به طور کلی، یک تخمین بسیار محافظه کارانه می تواند این باشد که هزینه های CPU تا 5٪ در موضوعات کلیدی کاهش می یابد. ممکن است نتایج متفاوتی ببینید.
سربار ابزار دقیق
ابزار دقیق PGO جامع است، و در حالی که به طور خودکار تولید می شود، رایگان نیست. هزینه سربار ابزار دقیق PGO ممکن است بسته به پایگاه کد شما متفاوت باشد.
هزینه عملکرد ابزار دقیق هدایت شده توسط نمایه
ممکن است با ساختهای ابزاردار شاهد کاهش نرخ فریم باشید. در برخی موارد - بسته به میزان استفاده از CPU شما در طول عملکرد عادی به 100٪ - ممکن است این افت آنقدر زیاد باشد که گیم پلی عادی را دشوار کند.
ما توصیه می کنیم که اکثر توسعه دهندگان یک حالت پخش نیمه قطعی برای بازی خود بسازند. این نوع عملکرد به تیم QA شما این امکان را می دهد که بازی را در یک مکان شروع شناخته شده و قابل تکرار در بازی شما (مانند یک بازی ذخیره یا سطح تست خاص) شروع کند و سپس ورودی خود را ثبت کند. این ورودی ضبط شده از ساخت آزمایشی را می توان به یک ساخت PGO-Instrumented وارد کرد، پخش کرد و داده های نمایه دنیای واقعی را بدون توجه به مدت زمانی که برای پردازش یک فریم نیاز دارد تولید کرد - حتی اگر بازی آنقدر آهسته اجرا شود که غیر قابل پخش
این نوع عملکرد مزایای عمده دیگری نیز دارد، مانند افزایش تلاش تستر: یک تستر میتواند ورودی خود را روی یک دستگاه ضبط کند، و سپس میتواند در چندین نوع مختلف دستگاه برای اهداف تست دود پخش شود.
سیستم پخش مجدد مانند این می تواند مزایای زیادی در Android داشته باشد، جایی که تعداد زیادی از انواع دستگاه ها در اکوسیستم وجود دارد - و مزایا به همین جا ختم نمی شود: می تواند بخش اصلی سیستم ساخت یکپارچه سازی مداوم شما را نیز تشکیل دهد و به شما امکان می دهد آزمایشات رگرسیون عملکرد و دود به طور منظم یک شبه را انجام دهید.
ضبط باید ورودی کاربر را در مناسب ترین نقطه در مکانیزم ورودی بازی شما ثبت کند (احتمالاً رویدادهای صفحه لمسی مستقیم نیست، بلکه پیامدهای آنها را به عنوان دستور ضبط می کند). این ورودیها همچنین باید دارای تعداد فریمهایی باشند که در طول گیمپلی بهطور یکنواخت افزایش مییابد، به طوری که در حین پخش، مکانیسم پخش مجدد میتواند منتظر فریم مناسبی باشد که روی آن باید یک رویداد را آغاز کند.
در حالت پخش، بازی شما باید از ورود آنلاین اجتناب کند، نباید تبلیغات را نشان دهد و باید در یک مرحله زمانی ثابت (با نرخ فریم هدف شما) کار کند. شما باید vsync را غیرفعال کنید.
مهم نیست که همه چیز (به عنوان مثال، سیستم های ذرات) در بازی شما کاملاً قطعی قابل تکرار باشد، اما اقدامات یکسان باید نتایج و نتایج یکسانی را در بازی ارائه دهند - یعنی گیم پلی باید یکسان باشد.
هزینه حافظه ابزار دقیق هدایت شده توسط پروفایل
سربار حافظه ابزار دقیق PGO بر اساس کتابخانه خاصی که کامپایل می شود بسیار متفاوت است. در آزمایشهای خود شاهد افزایش کلی اندازه آزمون قابل اجرا به میزان 2.2 برابر بودیم. این افزایش اندازه شامل کد اضافی مورد نیاز برای ابزارسازی بلوکهای کد و فضای مورد نیاز برای ذخیره شمارندهها میشود. این تست ها جامع نبودند و تجربه شما ممکن است متفاوت باشد.
چه زمانی دادههای نمایهتان را بهروزرسانی یا کنار بگذارید
هر زمان که تغییر زیادی در کد (یا محتوای بازی) خود ایجاد کردید، باید پروفایل های خود را به روز کنید.
این دقیقاً به محیط ساخت شما و جایی که در حال توسعه هستید بستگی دارد.
همانطور که قبلا ذکر شد، شما نباید داده های نمایه را در میان تغییرات عمده محیط ساخت حمل کنید. در حالی که این شما را از ساختن یا شکستن ساختنتان باز نمیدارد، اما مزایای عملکرد استفاده از PGO را کاهش میدهد، زیرا دادههای نمایه بسیار کمی برای محیط ساخت جدید قابل اعمال خواهد بود. با این حال، این تنها موردی نیست که ممکن است اطلاعات نمایه شما کهنه شود.
بیایید با این فرض شروع کنیم که از PGO تا پایان توسعه و زمانی که در حال آماده شدن برای انتشار هستید استفاده نخواهید کرد، فراتر از جمعآوری یک عکس هفتگی به طوری که مهندسان متمرکز بر عملکرد بتوانند تأیید کنند که هیچ مشکل غیرمنتظرهای وجود نخواهد داشت. نزدیکتر به انتشار
با نزدیک شدن به پنجره انتشار خود، زمانی که تیم QA شما هر روز در حال آزمایش است و به طور کامل بازی را اجرا می کند، این تغییر می کند. در طول این مرحله میتوانید پروفایلهایی را روزانه از آن دادهها تولید کنید و از آنها برای اطلاعرسانی به ساختهای آینده برای آزمایش عملکرد و تنظیم بودجه عملکرد خود استفاده کنید.
هنگامی که برای انتشار آماده میشوید، باید نسخه ساختی را که قصد انتشار آن را دارید قفل کنید و سپس QA را از طریق آن اجرا کنید تا دادههای نمایه جدید شما تولید شود. سپس با استفاده از این داده ها می سازید تا نسخه نهایی فایل اجرایی خود را تولید کنید.
پس از آن QA می تواند به این ساخت حمل و نقل بهینه سازی شده، یک مرحله نهایی را ارائه دهد تا اطمینان حاصل شود که انتشار آن خوب است.