چرا دو تخصیص‌دهنده؟ خلاصه‌ای سریع

کرنل باید هم حافظهٔ فیزیکی پیوسته را تأمین کند و هم تخصیص سریع و کم‌هزینهٔ اشیاء کوچک را ممکن سازد. برای این دو نیاز از دو راهبرد مکمل استفاده می‌شود: تخصیص‌دهنده بادی برای مدیریت بلوک‌های صفحه‌ای و حافظهٔ پیوسته، و تخصیص‌دهنده اسلب برای کش‌سازی و تخصیص اشیاء هم‌اندازه.

تخصیص‌دهنده بادی — مدیریت بلوک‌های توان دو

تخصیص‌دهنده بادی حافظهٔ فیزیکی را در بلوک‌هایی با اندازه‌های توان دو نگه می‌دارد. وقتی زیرسامانه‌ای مثلاً 25 کیلوبایت درخواست می‌دهد، نزدیک‌ترین اندازهٔ توان دو (مثلاً 32 کیلوبایت) انتخاب شده و در صورت نیاز بلوک‌ها تقسیم می‌شوند. ساختار سلسله‌مراتبی، یافتن و ادغام بلوک‌های آزاد را ساده می‌کند و از تکه‌تکه‌شدگی خارجی با همجوشی (coalescing) جلوگیری می‌نماید.

نقش بادی زمانی مشخص می‌شود که سخت‌افزار نیاز به حافظهٔ فیزیکی پیوسته دارد؛ برای مثال عملیات Direct Memory Access (DMA) به صفحات هم‌جوار نیاز دارد. هر ناحیهٔ حافظه فهرست‌هایی بر مبنای اندازه نگه می‌دارد و با لیست‌های پیوندی بلوک‌ها را مدیریت می‌کند.

مزایا

  • تضمین تخصیص صفحات فیزیکی پیوسته.
  • همجوشی بلوک‌های آزاد برای کاهش تکه‌تکه‌شدگی خارجی.

معایب

  • پایبندی به اندازه‌های توان دو می‌تواند تکه‌تکه‌شدگی داخلی ایجاد کند (مثلاً درخواست 36 کیلوبایت ممکن است 64 کیلوبایت تخصیص یابد).
  • برداشت و ادغام بلوک‌ها می‌تواند تاخیر قابل توجهی—در حد ده‌ها میکروثانیه—ایجاد کند که در بارهای با تاخیر بسیار کم گلوگاه می‌شود.

تخصیص‌دهنده اسلب — کش اشیاء و کاهش سربار

تخصیص‌دهنده اسلب اشیاء هم‌اندازه را در کشهای اختصاصی نگه می‌دارد. هر کش از چند اسلب تشکیل می‌شود؛ هر اسلب مجموعه‌ای از اسلات‌های اشیاء روی یک یا چند صفحهٔ فیزیکی است. هنگام تخصیص، اسلب به‌سرعت یک اسلات را بازمی‌دهد و هنگام آزادسازی همان اسلات قابل استفاده می‌شود؛ این رفتار سربار تخصیص را بسیار کاهش می‌دهد.

برای مروری فنی بیشتر به صفحهٔ Slab allocator در ویکی‌پدیا مراجعه کنید.

مزایا

  • تخصیص و آزادسازی بسیار سریع (معمولاً O(1)) و کاهش فراخوانی‌های سنگین به سطح بادی.
  • کاهش تکه‌تکه‌شدگی داخلی با نگهداری اشیاء هم‌اندازه در کش‌های جداگانه.
  • امکانات اشکال‌زدایی و بررسی حافظه، از جمله red-zoning، سازنده/مخرب اشیاء و ردیابی نشتی.

معایب

  • مناسب اشیاء با اندازهٔ ثابت است و برای نیاز به حافظهٔ فیزیکی پیوسته یا اشیاء با اندازهٔ بسیار متغیر مناسب نیست.
  • اگر مدیریت اسلب‌ها بهینه نباشد، خود اسلب‌ها می‌توانند منبع تکه‌تکه‌شدگی صفحه‌ای شوند.

اسلب‌ها معمولاً در سه حالت نگهداری می‌شوند: پر، نیمه‌پر و خالی؛ این وضعیت‌ها به تخصیص‌دهنده امکان می‌دهد بار را متعادل کند و حافظهٔ اضافی را آزاد نماید.

پیاده‌سازی‌های متداول در لینوکس

لینوکس چند پیاده‌سازی اسلب ارائه می‌دهد که هر یک هدف متفاوتی دنبال می‌کنند: SLAB با امکانات اشکال‌زدایی، SLUB برای ساده‌سازی و کارایی و SLOB برای سیستم‌های با حافظهٔ محدود. مستندات رسمی کرنل مرجع مفیدی است: Linux memory management.

راهنمای عملی: چه زمانی از کدام استفاده کنیم

  • در نیاز به حافظهٔ فیزیکی پیوسته یا صفحات بزرگ (مثلاً DMA یا تخصیص صفحات بزرگ برای درایورها)، از بادی استفاده کنید.
  • برای ساختارهای با اندازهٔ ثابت و تخصیص/آزادسازی مکرر (مانند descriptorها، inodeها، ساختارهای شبکه)، تخصیص‌دهنده اسلب مناسب‌تر است.
  • برای کاهش قفل‌زدگی و افزایش مقیاس‌پذیری در سامانه‌های چندهسته‌ای، از کش‌های per‑CPU و پیاده‌سازی‌هایی مانند SLUB بهره ببرید.
  • در محیط‌های NUMA مطمئن شوید تخصیص‌ها به ناحیهٔ حافظهٔ نزدیک به CPU موردنظر انجام شود تا تاخیر حافظه کاهش یابد.

حمل‌ونقل بین سطوح: تعامل اسلب و بادی

در عمل، اسلب و بادی مکمل هم‌اند. اسلب برای ارائهٔ سریع اشیاء از حافظهٔ آماده‌شده استفاده می‌کند و در صورت نیاز به صفحات جدید از بادی درخواست می‌دهد. وقتی صفحات آزاد می‌شوند، بادی با همجوشی آن‌ها بلوک‌های بزرگ‌تر تولید می‌کند که می‌تواند دوباره توسط اسلب‌ها مصرف یا بازپس‌گیری شود. طراحی مؤثر بر هماهنگی این دو سطح مبتنی است.

چشم‌انداز توسعه

با رشد بارهای کاری جدید—مانند مجازی‌سازی سنگین، eBPF و حافظهٔ پایدار با تاخیر کم—طراحی تخصیص‌دهنده‌ها پیوسته تکامل می‌یابد. تمرکزهای اصلی توسعه عبارت‌اند از: مقیاس‌پذیری بهتر در هسته‌های متعدد، کاهش تاخیر در مسیر تخصیص و استفادهٔ مؤثر از معماری‌های حافظهٔ نوین.

نتیجه‌گیری و توصیه‌های عملی

  • برای نیازهای حافظهٔ پیوسته و صفحات بزرگ: بادی؛ برای تخصیص‌های کوچک و سریع و اشیاء هم‌اندازه: تخصیص‌دهنده اسلب.
  • در سامانه‌های با چند هسته یا بار بالا، از پیاده‌سازی‌هایی که کش‌های per‑CPU و همگامی کمتر را پشتیبانی می‌کنند استفاده کنید.
  • نظارت بر تکه‌تکه‌شدگی و رفتار تخصیص در شرایط واقعی کار، کلید انتخاب یا تنظیم درست پیاده‌سازی است.

برای مطالعهٔ فنی بیشتر دربارهٔ تکه‌تکه‌شدگی حافظه به Memory fragmentation و برای مروری بر APIهای تخصیص کِرنل به مستندات هستهٔ لینوکس مراجعه کنید.