وبلاگ
چگونه بازیسازان با بهینهسازی I/O از سختافزارهای پایینتر بهره میبرند؟
در دنیایی که هر ساله یک بازی جدید با چندین ترابایت داده از افق ظاهر میشود، توانایی اجرا در سختافزارهای متوسط و حتی کمقدرت، نه تنها یک مزیت رقابتی، بلکه یک ضرورت بقا است. بازیسازان امروزه دیگر صرفاً به **پردازندههای قدرتمند** یا **کارتهای گرافیکی** پیشرفته اکتفا نمیکنند؛ بلکه به سمت بهینهسازی عمیق مسیرهای ورودی/خروجی (I/O) حرکت کردهاند. این بهینهسازی، شکلی از هنر است که در ظاهر ساده به نظر میرسد، اما در پشت صحنه، هزاران خط کد، طراحی فایلها، و مدیریت حافظه را در بر میگیرد. هنگامی که یک کنسول قدیمی یا یک پیسی با هارد دیسک مکانیکی، بازیای را اجرا میکند که برای SSDهای نسل جدید طراحی شده، نتیجه یک معجزه فنی است. این معجزه، نتیجه تلاشهای تیمهای مهندسی است که به جای انتظار برای سختافزار بهتر، به جایی رسیدهاند که سختافزار ضعیف را به یک ابزار قدرتمند تبدیل کنند. این مقاله، رازهای پشت صحنه این تبدیل را با جزئیات بینظیر بررسی میکند. ما در irantech نه تنها به اینکه چگونه I/O بهینه میشود، بلکه به اینکه چرا این بهینهسازی، جان بازی است، میپردازیم.
آشنایی و مقدمهای بر I/O در بازیسازی
در هر بازی مدرن، از لحظهای که کاربر دکمه پاور را فشار میدهد تا زمانی که اولین صحنه بازی را تجربه میکند، دهها فرآیند I/O در پسزمینه انجام میشود. فایلهای مدلهای ۳D، صداهای پسزمینه، نقشههای بازی، متادیتا، تکستچرها، و حتی کدهای اجرایی — همه اینها از دیسک یا حافظه پایدار (Storage) به حافظه رم (RAM) منتقل میشوند. این انتقال، اگر به درستی مدیریت نشود، باعث تأخیرهای نامطلوب، فریزهای ناگهانی، یا حتی کاهش فریمریت میشود. اما در حالی که بسیاری فکر میکنند که این مشکل تنها با خرید SSD حل میشود، بازیسازان با دانش عمیقتری، این فرآیند را از داخل بازی تغییر میدهند. آنها نه تنها دادهها را کمتر میکنند، بلکه روشهای دسترسی، ترتیب بارگذاری، و نحوه ذخیرهسازی را کاملاً بازطراحی میکنند. این کار، در اصل، به معنای تبدیل یک دیسک کند به یک ابزار تقریباً لحظهای است. به عبارت دیگر، بهینهسازی I/O، یعنی «کار کردن با آنچه داری، نه آنچه میخواهی».
چرا I/O یکی از بزرگترین محدودیتهای امروزه است؟
اگرچه پردازندهها و کارتهای گرافیکی در دهه اخیر به سرعت پیشرفت کردهاند، اما سرعت دسترسی به دادههای ذخیرهشده — یعنی I/O — به همان نرخ نرفته است. این عدم توازن، به عنوان **I/O Bottleneck** شناخته میشود. یک GPU مدرن میتواند در یک ثانیه میلیاردها پیکسل را رندر کند، اما اگر دادههای مورد نیاز برای هر پیکسل از یک هارد دیسک مکانیکی (HDD) بارگیری شود، این قدرت کاملاً بیفایده میشود. حتی در سیستمهای با SSD، اگر دادهها به درستی سازماندهی نشوند، دسترسی تصادفی (Random Access) میتواند سرعت را به شدت کاهش دهد.
این محدودیت، به ویژه در بازیهای با دنیای باز (Open World) بسیار حیاتی است. در بازیهایی مثل *Red Dead Redemption 2* یا *Cyberpunk 2077*، میلیونها فایل در طول بازی بارگیری و آزاد میشوند. اگر هر بار که بازیکن به یک منطقه جدید میرود، سیستم باید صدها فایل را از دیسک بخواند و آنها را در RAM قرار دهد، تأخیر ناگهانی (Stutter) و لاتنسی (Latency) اجتنابناپذیر خواهد بود. بنابراین، **بهینهسازی I/O** نه تنها بهبود عملکرد را هدف میگیرد، بلکه **تجربه کاربری را نجات میدهد** که توسط بازیسازان انجام میشود.
استراتژیهای کلیدی بهینهسازی I/O
در این بخش، به تفصیل به چهار استراتژی اساسی که تیمهای توسعه بازی از آنها استفاده میکنند، میپردازیم. این استراتژیها نه تنها در پروژههای بزرگ، بلکه در بازیهای مستقل نیز به کار گرفته میشوند — گاهی با تفاوتهای جزئی، اما با همان اصول بنیادی:
فشردهسازی هوشمندانه دادهها/ Intelligent Data Compression
فشردهسازی تنها به معنای کوچکتر کردن فایلها نیست. اینجا، فشردهسازی با توجه به الگوهای دسترسی انجام میشود. برای مثال، تکستچرهایی که در فاصله نزدیک دیده میشوند، با فشردهسازی lossy (مانند DXT یا ASTC) ذخیره میشوند، در حالی که تکستچرهای کلیدی (مانند چهره شخصیتها) با فشردهسازی lossless (مانند PNG یا Zstandard) نگهداری میشوند. این روش، حجم دادهها را تا ۷۰٪ کاهش میدهد، بدون آنکه کیفیت بصری قابل توجهی از دست برود.
بارگیری پویا و پیشبارگیری/ Dynamic & Prefetching Loading
سیستمهای مدرن بازی، از تکنیکهایی مانند **streaming** و **prefetching** استفاده میکنند. به جای بارگیری کل نقشه در یک زمان، فقط بخشهایی که نزدیک به بازیکن هستند، بارگیری میشوند. اما نکته کلیدی اینجاست: سیستم، نه فقط آنچه نیاز دارد، بلکه آنچه **احتمالاً** نیاز خواهد داشت را پیشبارگیری میکند. این کار با تحلیل مسیر حرکت بازیکن، الگوهای رفتاری، و حتی احتمالات ریاضی انجام میشود. مثلاً اگر بازیکن به سمت یک پل میرود، سیستم پیشبینی میکند که احتمالاً بعد از پل، یک میدان جنگی خواهد دید — و پیشاً تمام مدلهای آن را در حافظه آماده میکند.
استفاده از ساختارهای داده بهینهشده برای دسترسی سریع/ Optimized Data Structures
دادهها در دیسک نباید به صورت تصادفی یا غیرمنسجم ذخیره شوند. تیمهای توسعه، از ساختارهایی مانند **B-Trees**، **Octrees**، و **Spatial Hashing** استفاده میکنند تا دادههای فضایی (مثلاً اشیاء در یک منطقه خاص) به صورت منطقی و مجاور در دیسک قرار گیرند. این کار باعث میشود که یک عملیات خواندن (Read Operation) چندین فایل را در یک تکرار از دیسک بخواند — که به شدت کاهش دهنده تعداد I/O Operations است.
مدیریت حافظه بازی/ Memory Pooling & Object Recycling
به جای بارگیری و آزادسازی مداوم اشیاء (مانند سنگها، درختان، یا اشیاء متحرک)، یک حافظه پول (Memory Pool) ایجاد میشود. این پول، اشیاء را در حافظه نگه میدارد و آنها را با فعال/غیرفعال کردن (Activate/Deactivate) مدیریت میکند. این روش، نیاز به بارگیری مجدد فایلها را از دیسک کاملاً حذف میکند و به جای آن، فقط یک اشارهگر (Pointer) را تغییر میدهد — که چند میکروثانیه طول میکشد.
نقشهبرداری دادهها/ از فایلهای پراکنده به یک دیسک منسجم
یکی از بزرگترین اشتباهات در توسعه بازی، توزیع نادرست دادهها روی دیسک است. تصور کنید که یک بازی شامل ۵۰,۰۰۰ فایل تکستچر باشد — هر کدام در یک پوشه متفاوت، با نامهای تصادفی، و در مکانهای مختلف فیزیکی روی دیسک ذخیره شده باشند. هنگامی که بازیکن وارد یک منطقه جدید میشود، سیستم باید ۵۰۰ فایل را از ۵۰۰ مکان متفاوت روی دیسک بخواند. در هارد دیسک مکانیکی، این کار میتواند چند ثانیه طول بکشد — زمانی که یک بازیکن انتظار دارد که دنیا به سرعت باز شود.
برای حل این مشکل، تیمهای توسعه از **Data Layout Optimization** استفاده میکنند. این فرآیند شامل سه مرحله اصلی است:
- Analyzing Access Patterns با استفاده از ابزارهایی مانند **PerfView** یا **Intel VTune**، تیمها مشاهده میکنند که کدام فایلها در کدام لحظات از بازی بارگیری میشوند.
- **Reordering Data on Disk**: فایلهایی که به طور متوالی بارگیری میشوند، در دیسک به صورت مجاور قرار میگیرند. این کار، تعداد سرنشینهای هد (Head Seek) را در HDD کاهش میدهد — که بزرگترین عامل تأخیر در دیسکهای مکانیکی است.
- Packaging into Containers**: به جای ذخیره هر فایل به صورت جداگانه، تمام دادههای یک منطقه (مثلاً یک شهر) در یک فایل بزرگ (Container File) — مانند `.pak` در اونتیل یا `.assetbundle` در یونیتی — بستهبندی میشوند. این کار، نه تنها تعداد فایلهای باز شده را کاهش میدهد، بلکه امکان کشکردن (Caching) کل بلوک داده را فراهم میکند.
این روش، در بازی *Halo Infinite*، باعث شد که زمان بارگیری مناطق جدید از ۱۲ ثانیه به کمتر از ۳ ثانیه کاهش یابد — حتی روی یک HDD سنتی.
ابزارهای پیشرفته و سفارشیسازیهای داخلی
بسیاری از استودیوها، به جای استفاده از ابزارهای پیشفرض مانند Unreal Engine 5’s **Virtual Texturing** یا Unity’s **Addressables**، ابزارهای سفارشی (Custom I/O Systems) میسازند. این ابزارها، دقیقاً برای نیازهای خاص بازی طراحی میشوند. به عنوان مثال، تیم *CD Projekt Red* در توسعه *Cyberpunk 2077*، یک سیستم I/O سفارشی به نام **“Data Streamer”** توسعه دادند که:
- دادهها را به صورت **پیشپردازشی (Pre-processed)** در حین ساخت بازی، بر اساس مسیرهای پیشبینیشده مرتب میکرد.
- از **Compression Profiles** متفاوت برای هر نوع داده (صدا، مدل، تکستچر) استفاده میکرد.
- یک **Priority Queue** داشت که دادههای حیاتی (مانند شخصیت اصلی یا دشمنان نزدیک) را با اولویت بالا بارگیری میکرد.
این سیستم، حتی روی پیسیهای با ۸ گیگابایت رم و HDD، امکان اجرای بازی را بدون فریزهای طولانی فراهم کرد — در حالی که نسخه استاندارد اونتیل در همان سختافزار، کاملاً ناپایدار بود.
ابزارهای دیگری نیز در این زمینه محبوب هستند:
- RapidIO (توسعهیافته توسط Epic برای Unreal Engine 5)
- Steam’s Content Streaming API
- Google’s Brotli Compression (برای فایلهای متنی و JSON)
- Microsoft’s DirectStorage API (که اجازه میدهد SSD مستقیماً به GPU داده بفرستد — بدون نیاز به CPU)
حتی در بازیهای مستقل، توسعهدهندگان از کتابخانههایی مانند **libdeflate** یا **zstd** برای فشردهسازی سریع استفاده میکنند — چرا که هر میلیثانیه که از زمان بارگیری کاهش یابد، تجربه کاربری بهتر میشود.
آزمون، اندازهگیری و بهینهسازی مداوم I/O
بهینهسازی I/O، یک فرآیند یکباره نیست. این یک **چرخه مداوم** است که توسط بازیسازان در سه مرحله اصلی انجام میشود:
1. Logging & Profiling
هر بار که بازی اجرا میشود، یک لگ دقیق از تمام عملیات I/O ثبت میشود — شامل زمان، حجم داده، نوع فایل، و موقعیت فیزیکی روی دیسک.
2. Heatmap Generation
این دادهها به صورت نقشه گرمایی (Heatmap) نمایش داده میشوند. در این نقشه، مناطقی که بیشترین دسترسی را دارند، با رنگ قرمز و مناطق بیاستفاده با آبی نشان داده میشوند.
3. Iterative Refinement
با توجه به این نقشهها، تیمها فایلها را مجدداً مرتب میکنند، فشردهسازی را تنظیم میکنند، و ساختارهای داده را بهروز میکنند — و این فرآیند، هر هفته یا حتی روزانه تکرار میشود.
یکی از معروفترین مثالها، بازی *The Last of Us Part I* بود که تیم Naughty Dog، پس از انتشار، یک بهروزرسانی را منتشر کرد که زمان بارگیری را در PS4 از ۱۲ ثانیه به ۶ ثانیه کاهش داد — بدون تغییر در سختافزار، فقط با تغییر در چگونگی نگهداری دادهها.
چالشهای اخلاقی و فنی در بهینهسازی I/O
بهینهسازی I/O گاهی به معنای **فداکاری کیفیت** است. یک تکستچر ۴K میتواند به ۲K فشرده شود، صداهای استریو به مونو تبدیل شوند، یا مدلهای ۳D با کاهش پولیگون به سادهترین شکل خود تبدیل شوند. این تصمیمات، از نظر فنی، بهینه هستند — اما از نظر هنری، میتوانند به بحث تبدیل شوند. تیمهای موفق، این تعادل را با **Quality Thresholding** مدیریت میکنند. به این معنا که:
✔️ اگر سختافزار دارای SSD باشد → تکستچرهای ۴K بارگیری میشوند.
✔️ اگر HDD باشد → تکستچرهای ۲K بارگیری میشوند.
✔️ اگر رم کمتر از ۸ گیگابایت باشد → مدلهای ۱۰۰۰ پولیگونی به جای ۵۰۰۰ پولیگونی استفاده میشوند.
این سیستم، به صورت خودکار در زمان اجرا فعال میشود — و کاربر حتی متوجه تغییر نمیشود. اما این تغییر، یک **انتخاب آگاهانه** است — نه یک اشتباه.
آینده I/O- از SSDهای نسل چهارم تا هوش مصنوعی
با ظهور فناوریهایی مانند **PCIe 5.0 SSD**، **DirectStorage 2.0**، و **NVIDIA RTX IO**، آینده بهینهسازی I/O دچار تحول شدیدی میشود. اما جالب اینجاست که بزرگترین پیشرفت، نه در سختافزار، بلکه در **هوش مصنوعی** است. شرکتهایی مانند NVIDIA و AMD، در حال توسعه سیستمهایی هستند که با استفاده از **ML Models** (مدلهای یادگیری ماشین)، پیشبینی میکنند که کاربر در چه منطقهای خواهد رفت — و از قبل تمام دادههای مورد نیاز را بارگیری میکنند. این سیستمها، دادههای گذشته بازیکن، حرکات چشم، سرعت تغییر جهت، و حتی سطح استرس او را تحلیل میکنند — و بر اساس آن، اولویتهای بارگیری را تغییر میدهند. این تکنیک، در آینده نزدیک، میتواند باعث شود که یک بازی با حجم ۱۰۰ گیگابایت، روی یک HDD قدیمی، به صورت نزدیک به لحظهای اجرا شود — بدون نیاز به هیچ تغییری در سختافزار.
همچنین مقاله های زیر را مطالعه نمایید:
کلام آخر/ بهینهسازی I/O توسط بازیسازان- هنری قدرتمند
بهینهسازی I/O، یکی از کمتر دیده شدهترین، اما پراثرترین جنبههای توسعه بازی است. در جهانی که تبلیغات بر سر قدرت GPU و تعداد هستههای پردازنده میچرخد، این تکنیکها در پشت صحنه، نه تنها بازیهایی را اجرا میکنند که بدون آنها ناممکن بودند، بلکه تجربه کاربری را از یک فرآیند آهسته به یک جریان بیدرنگ تبدیل میکنند. آنها نه تنها به سختافزارهای قدیمی عمر میدهند، بلکه به میلیونها کاربر در کشورهای در حال توسعه، دسترسی به تجربههای بازیسازی مدرن را میدهند. این فرآیند، نه یک راه حل، بلکه یک **فلسفه** است. ایران تک باور دارد که در این راه، مهندسان بازی (بازیسازان)، هنرمندانی هستند که با فایلها، دیسکها، و حافظهها میآفرینند — و نه تنها بازی را میسازند، بلکه آن را **زنده نگه میدارند**.
سوالات متداول
آیا بهینهسازی I/O فقط برای بازیهای بزرگ مهم است؟
خیر. حتی بازیهای کوچک با ساختار نادرست I/O، میتوانند با تأخیر و فریزهای ناگهانی مواجه شوند.
آیا SSD همیشه جواب میدهد؟
نه. اگر دادهها به درستی سازماندهی نشوند، SSD هم میتواند با تأخیر تصادفی مواجه شود.
چه ابزارهای رایگانی برای تحلیل I/O وجود دارد؟
PerfView (ویندوز)، iotop (لینوکس)، و Xcode Instruments (مک) ابزارهای قدرتمند و رایگان هستند.