مدیریت حافظه در جاوا اسکریپت

Image by netkids from Pixabay
Image by netkids from Pixabay

مدیریت حافظه در زبان‌های سطح پایین (پایین‌تر از جاوا اسکریپت!) مثل C می‌بایست از طرف برنامه‌نویس انجام شود. توابعی برای درخواست حافظه و آزادسازی آن وجود دارد که به فراخور نیاز می‌بایست به کار بسته شوند. ولی در زبان‌های سطح بالا مثل جاوا اسکریپت (یا مثلا جاوا) عملیات مدیریت حافظه در پشت صحنه به کمک فرآیندی مشهور به Garbage Collection انجام می‌شود.

فرآیند Garbage Collection

طبیعتا هر زمان متغییری تعریف شود، حافظه‌ای برای آن در نظر گرفته می‌شود.

var yekNumber = 20; // takhsise hafeze baraye number
var yekString = 'salam'; // takhsise hafeze baraye string 
var yekObject = { pi: 3.14 }; // takhsise hafeze baraye object
var yekArray = [ 10, 20, 3, 15, 1000, 'o', 60, 16]; // takhsise hafeze baraye array
function doBarabar(a) {
   return 2 * a;
} // takhsise hafeze baraye function

وقتی دیگر به آن حافظه نیازی نباشد، جاوا اسکریپت آن حافظه را آزاد می‌کند تا بعدا از آن برای مصارف دیگر استفاده شود. پیدا کردن حافظه‌هایی که دیگر مورد نیاز برنامه‌ نیستند بر عهده واحد Garbage Collector است. چیزی شبیه ماشین جمع آوری زباله از سطح شهر!

برای تشخیص حافظه‌های بلااستفاده چند الگوریتم استفاده می‌شود که دو الگوریتم اصلی آن‌ها معرفی می‌شود:

  • الگوریتم رفرنس-شماری Reference-counting garbage collection
  • الگوریتم نشان-و-گردش Mark-and-sweep algorithm

الگوریتم رفرنس-شماری

این مهمترین الگوریتم جمع آوری حافظه است. اگر در الگوریتم رفرنس-شماری، تعداد رفرنس‌های یک متغییر صفر باشد، حافظه آن متغییر (در راه خدا؟) آزاد می‌شود.

مثال

var khune = { divare_shomal: { panjere: 2 } };
// 2 object sakhte shode. "panjereh" be onvane propertie "divare_shomal" be shey-e "divare_shomal" reference mishavad

var khune = 'dasht'; // hafeze i k "divare_shomal" dar "khune" gerefter bud, hala digar reference nadarad va azad-saazi mishavad.


بحران حلقه

function hazfe_fesaad () {
   var masool = {};
   var ghanoon = {};
   
   ghanoon.sazande = masool;
  masool.sazande = ghanoon;
  
      return 'ok.';
}

همانطور که در قطعه کد بالا دیده می‌شود متغییر masool در ghanoon رفرنس شده است و متغییر ghanoon در متغییر masool مورد رفرنس قرار گرفته است. دوستان، به چنین وضعیتی حلقه گفته می‌شود. وقتی که اسکوپ از این حلقه عبور کند با وجود اینکه این دو متغییر گرامی بلااستفاده هستند، این الگوریتم قادر به آزاد سازی حافظه‌ای که اشغال کرده‌اند نمی‌باشد و این‌ها همچنان به یکدیگر رفرنس خواهند داشت. این وضعیت باعث بروز نشت حافظه یا اصطلاحا memory leaks می‌شود. پدیده‌ای شیطانی که باعث انحطاط سیستم می‌شود. در اثر هر بار فراخوانی این متد، بیشتر و بیشتر حافظه مصرف می‌کند و وقتی دیگر حافظه‌ای باقی نماند سیستم به سراغ هارد می‌رود و پس از مدتی سیستم چنان درگیر خواهد شد که قادر به انجام هیچ کاری نخواهد بود. ساعت‌ها خواهد گذشت تا یک درخواست ساده ctrl + alt+ delete اجرا شود چون سیستم مشغول انتقال محتویات حافظه به هارد و هارد به حافظه خواهد بود.

الگوریتم نشان-و-گردش

سیستم جمع آوری حافظه از این الگوریتم برای آزاد سازی حافظه وقتی که یک متغییر دیگر در دسترس نیست استفاده می‌کند.

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


این نوشته با الهام از این متن که خود از نود سیمپیلی‌فاید اقتباس شده نوشته شده است.