مدیریت حافظه دوستانه

سیستم حافظهٔ رفاقتی چگونه کار می‌کند

فرم‌های گوناگونی از سیستم حافظه وجود دارد، اما رفاقتی دودویی که در آن هر بلاک به دو بلاک کوچکتر تقسیم می‌شود، ساده‌ترین و رایج‌ترین نوع آن هستند.
هر بلاک حافظه در این سیستم یک مرتبه دارد. در جایی که مرتبهٔ آن در بازهٔ یک عدد صحیح از ۰تا محدودهٔ بالایی مشخص شده‌است. بلاک‌ها در هر مرتبه دارای اندازه‌های متناسب با ۲ به توان مرتبه هستند، که هر بلاک دقیقآ دو برابر اندازهٔ بلاک‌هایی است که در یک مرتبه در محدودهٔ پایین‌تر هستند. توان دو اندازهٔ بلاک‌ها محاسبات آدرس را ساده می‌سازد، به این دلیل که همهٔ رفیق‌ها در یک ردیف از محدودهٔ آدرس روی حافظه هستند که توان‌هایی از دو می‌باشند. زمانی که یک بلاک بزرگتر تقسیم‌بندی می‌شود، این بلاک به دو بلاک کوچکتر تقسیم می‌شود و هر کدام از بلاک‌های کوچکتر یک رفیق یکتا برای دیگری می‌شود. یک بلاک بخش بندی شده فقط با یک بلاک رفیق یکتای خودش می‌تواند ترکیب شود که به یک بلاک بزرگتر از آن (که از آن به دو نیم شده بودند) باز سازی شوند.
در ابتدا، اندازهٔ کوچکترین بلاک ممکن تصمیم‌گیری می‌شوند (معین می‌شوند) کوچکترین بلاکی از حافظه که می‌تواند تخصیص داده شود. اگر هیچ محدودیت دیگر ی وجود نداشت،(تخصیص‌های به اندازهٔ بیتی ممکن می‌باشند) ممکن است به ازای هر سیستم حافظه و سربارهای محاسباتی زیادی برای دنبال کردن تخصیص و عدم تخصیص بخش‌های حافظه داشته باشیم، به هر حال در محدوده‌ها ی پایین‌تر که ممکن است قابل توصیف باشد، میانگین حافظهٔ به هدر رفته به ازای هر تخصیص (تخصیص‌هایی که برای هر اندازه وجود دارند را در گیر می‌کند، نه بلاک‌های متعدد کوچکتر را) به حداقل رسیده است.
معمولآ محدودهٔ سطح پایین‌تر به اندازهٔ کافی کوچک هست که بتواند حافظهٔ تخصیص یافته به ازای هر تخصیص را به حد اقل برساند و همچنین به اندازهٔ کافی هم بزرگ هست که از سر بار بیش از اندازه جلوگیری کند. کوچکترین اندازهٔ بلاک به عنوان اندازهٔ بلاک در مرتبهٔ ۰ در نظر گرفته می‌شود، بنابراین تمام مرتبه‌های در سطح بالاتر به صورت توان‌هایی از دو از اندازه‌های متعدد می‌باشند.
برنامه‌نویس سپس روی نوشتن کد برای دستیابی به بالاترین مرتبهٔ ممکن که متناسب با فضای در دسترس از حافظهٔ باقی‌مانده می‌باشد، تصمیم‌گیری می‌کند.
از انجایی که کل حافظهٔ در دسترس به سیستم کامپیوتری داده شده، ممکن است توانی از دو به ازای کوچکترین اندازه‌های بلاک نباشد، بزرگترین اندازهٔ بلاک ممکن است کل حافظهٔ سیستم را پوشش ندهد. به عنوان نمونه، اگر سیستم 2000k حافظهٔ فیزیکی داشته باشد و اندازهٔ بلاک مرتبهٔ 0,4k باشد، محدودهٔ بالایی مرتبهٔ ۸می‌شود. از آنجایی که یک بلاک مرتبهٔ ۸ (۲۵۶ تا بلاک مرتبهٔ ۰ متناظر با 1024k) بزرگترین بلاک متناسب با حافظه خواهد بود؛ بنابراین این امکان‌پذیر است که یک حافظهٔ فیزیکی کامل را به یک بخش بزرگ واحد تخصیص دهیم. باقی ماندهٔ 967k از حافظه ممکن است به بلاک‌های کوچکتر تخصیص داده شود.

پیاده‌سازی و کارایی

در مقایسه با تکنیک‌ها ی ساده‌تر مانند تخصیص حافظهٔ پویا، تخصیص حافظه‌ای رفیق، مقدار کمی تکه‌تکه شدن خارجی دارد و با سربار کمی به حافظه اجازهٔ فشرده سازی می‌دهد. متد رفیق برای آزاد سازی حافظه (که با بیشترین تعداد فشرده سازی مورد نیاز برابر با لگاریتم ۲ (بالاترین مرتبه) است) سریع است.
معمولآ سیستم حفاظتی رفیق با استفاده از درخت دودویی برای نمایش بلاک‌های حافظهٔ دو نیم شدهٔ استفاده شده ویا نمایش بلاک‌های حافظهٔ دو نیم شدهٔ استفاده نشده، پیاده‌سازی می‌شود. رفیق هر بلاک می‌تواند با آدرس بلاک انحصاری و اندازهٔ بلاک پیدا شود.
به هر حال هنوز مشکل تکه‌تکه شدن داخلی وجود دارد. حافظه به هدر می‌رود به خاطر اینکه حافظهٔ در خواست شده یک مقدار کمی از اندازهٔ کوچکترین بلاک کمتر است، اما خیلی کوچکتر از بلاک بزرگ است.
برای اینکه سیستم تخصیص رفاقتی کار کند، به یک برنامه‌ای که 66k حافظه را در خواست کرده‌است، 128k اختصاص یافته‌است، که در نتیجه 62k حافظه به هدر رفته است. این مشکل می‌تواند با تخصیص قطعه (slab allocation) حل می‌شود؛ که به بالای درشت‌ترین اختصاص رفاقتی لایه بندی می‌شود تا تخصیص (fine–grain) بیشتری را فراهم کند.
یک نسخه از الگوریتم تخصیص حافظه با جزییات توسط دانلد کنوت در جلد ۱ از کتاب هنر برنامه‌نویسی کامپیوتر شرح داده شده‌است. در امتداد اختصاص‌های گوناگون دیگر برای مدیریت کردن حافظه‌های درون بلاکی، هستهٔ لینوکس همچنین برای سیستم رفاقتی به همراه اصلاحات بیشتری برای به حد اقل رساندن تکه‌تکه شدن خارجی، استفاده می‌شود. در میان دیگران و تکنیک‌های رفاقتی jemalloc یک اختصاص دهندهٔ حافظهٔ مدرن است که به کار گرفته می‌شود.