JavaScriptda xotira boshqaruvi va garbage collector

Assalamu Alaykum bugun JavaScriptda qiyinroq mavzu xotira qanday boshqarilishi hamda o'zgaruvchilar qanday yaratilib o'chirilishini ko'rib chiqamiz .

Bugungi maqolada :

  1. Xotira managmenti

  2. Xotira sikli

  3. Garbage Collection

  4. Garbage Collection algoritmlari

Xotira managmenti

Low level dasturlash tillarida masalan C, C++ larda xotirani boshqarish dasturchi tomonidan 'malloc()' va'free()' funksiyalarini ishlatish orqali amalga oshiriladi. Ammo JavaScriptda bu jarayon avtomatik bo'lib obyektlar yaratilganda xotirani o'zi joy ochib uni ishlatilinishi tugagandan so'ng o'chirib tashlanadi garbage collector tomonidan. Buning natijasida ko'p dasturchilar xotira managmenti haqida o'ylashmaydi. Va bu ba’zan keraksiz ma’lumotlar xotirada o'chirilmasdan(memory leak)qolib ketishiga olib keladi.

Xotira sikli

Qanday dasturlash tili bo'lishidan qatiy nazar deyarli hammasida xotira sikli bir xil bo'ladi:

xotira sikli
xotira sikli
  1. Kerakli xotirani ajratish

  2. Yozish va o'qish (read, write) uchun xotiradan foydalanish

  3. Ajratilgan xotirani kerak bo'lmaganda o'chirib yuborish.

2 qism hamma dasturlash tillarida dasturchi tomonidan qilinadi . 1 va 3 qisma low level dasturlarda dasturchi tominidan high-level Javascriptga o'xshaganlarda esa til tomonidan amalga oshiriladi .

Xotirani ajratish

const n = 123; // allocates memory for a number
const s = "azerty"; // allocates memory for a string

const o = {
  a: 1,
  b: null,
}; // allocates memory for an object and contained values

// (like object) allocates memory for the array and
// contained values
const a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener(
  "click",
  () => {
    someElement.style.backgroundColor = "blue";
  },
  false,
);

Xotiradan foydalanish

Xotiradan foydalanish bu o'zgaruvchini o'qish uni o'zgartirish yoki funksiyaga argument sifatida berish kiradi .

Xotirani bo'shatish

Juda ko'p xotira boshqarish muammolari ushbu qismda yuzaga keladi .Bu yerdagi eng katta muammo bu ajratilga xotira qachon kerakmasligini aniqlash .Bu haqida to'liq Garbage Collection bo'limida gaplashamiz.

Garbage collection

Javascriptda xotirani boshqarishning asosiy konsepsiyasi bu reachability (ya’ni unga yetib bo'ladimi).

Oddiy qilib aytganda yetib borish mumkin bo'lgan qiymatlar kerakli deb hisoblanadi va ular xotirada saqlanishi taminlanadi . Yetib borish deganda nima tushuniladi bu deganini shu o'zgaruvchi dastur ishlash davomida qaysidir referencelar bilan ishlatilinsa (dasturni ishlashi uchun kerak ) reachable qiymatlar deyiladi.

Ammo shunchaki reachable qiymat bo'lmasa ham o'chirib yuborish mumkin bo'lmagan narsalar ham bor .

Masalan :

  1. Hozirgi run bo'layotgan funksiyaning ichki o'zgaruvchilari.

  2. Global o'zgaruvchilar

  3. Ichma ich chaqirilgan boshqa funksiyalar va ularning ichki o'zgaruvchilari.

Endi buni misollar orqali ko'ramiz:

let daraxt = {
  boy:180, 
  eni:20
}

Hozirda bizdagi daraxt o'zgaruvchisida _{ boy:180, eni:20}_degan obyektga reference bor.

global o`zgaruvchilar bog`lanishi
global o`zgaruvchilar bog`lanishi

agarda biz daraxt = null qilsak bu reference yo'qoladi va obyekt xotiradan o'chirib yuboriladi.

o'chirib yuborilish jarayoni
o'chirib yuborilish jarayoni

2 talik reference

Tasavvur qiling endi daraxt o'zgaruvchisini terak o'zgaruvchisiga tenglashtiramiz .

let daraxt = {
  boy:180, 
  eni:20
}

let terak = daraxt 
2 talik bog'lanish
2 talik bog'lanish

Agarda biz yana daraxt=null qilsak ham obyekt o'chib ketmaydi chunki unga yana bir reference bor.

daraxt nullga tenglangan payti
daraxt nullga tenglangan payti

Endi murakkabroq obyektda ko'ramiz .

function bola(ism, erkak, ayol) {
  ayol.er = erkak;
  erkak.xotin = ayol;

  return {
    bola: ism,
    ota: erkak,
    ona: ayol
  }
}

let oila = bola("Bobut",{
  ism: "Farhod"
}, {
  ism: "Shirin"
});
xotiradagi bog'lanishlar
xotiradagi bog'lanishlar

delete keywordi orqali referenceni o'chirib yuborsa bo'ladi.

delete oila.ota;
delete oila.ona.er;

ota obyektiga referencelar qolmaganligi tufayli bu obyekt xotiradan o'chiriladi.

Ichki algorithmlar

Qani endi garbage collector qanday qilib obyektni o'chirib yuborishi mumkinligini ko'rib chiqamiz .Bunda asosiy 2 ta algoritmlar bor :

Reference-counting Algorithm

Bu algoritm 2lasi orasida eng oddiy algoritm hisoblanadi . Reference-counting algoritmida obyekt qanchuki unga kodda birorta reference topilmasa “axlat” hisoblanadi.Internet Explorer 6 and 7 asosan shu asosida ishlaydi hamda boshqalar shu bilan birgalikda mark and sweep algoritmi birgalikda ishlatilinadi.

Bu algoritmining eng zaif tomoni : circular referencelar bu algoritm orqali aniqlanmaydi.Agarda ikki o'zgaruvchi bir biriga reference qilgan holda ishlatilinsa va kodning biror joyida ishlatilinmasa ham u o'chirib yuborilmaydi chunki u “kerakli” deb hisbolanadi.

/* even if foo and bar don't exist outside this function, the reference-counting algorithm won't count these as ready for garbage collection */

function circularFunc() {
    const foo = {};
    const bar = {};
    foo.a = bar;
    bar.a = foo;
}

circularFunc();

Mark and Sweep Algorithm

Eng oddiy garbage collector algorithmlaridan biri bu mark-and sweep unda quyidagi boshqichlardan o'tiladi.

mark and sweep algoritmi
mark and sweep algoritmi

Bu javascriptda garbage collectorning umumiy qanday ishlashi edi . Javascript engine unga bir nechta optimizatsiyalar kiritadi (garbage collector tez ishlashi va code ishlashida kutishlar bo'lmasligi uchun).

Optimizatsiyaning bazilari :

Bundan tashqari har xil optimizatsiyalar usullari va algoritm usullari bor har bir Javascript engine bunga har xil yondashadi. Agarda bunga qiziqsangiz yanada chuqurroq izlanish irqali ko'proq ma’lumot topishingiz mumkin .

Garbage collectorlardagi doimiy yaxshilanishlarga qaramay, JavaScript-da _memory leaklar_ hali ham sodir bo’lishi mumkin. Memory leak bu keraksiz narsalarning xotirada saqlanishi tufayli ko'p xotira ishlatilinishi . Ularni amalga oshishining bir necha asosiy yo'li mavjud:

  1. Bilmasdan global o'zgaruvchilar e’lon qilish (global o'zgaruvchilar garbage collection o'chira olmaydi ).

  2. Timers setInterval orqali yaratilgan callback funksiyalar toki setInterval o'chmaguncha xotirada saqlanib turaveradi .Va garbage collector ularga yetib borolmaydi.

  3. Closure bu orqali o'zidan tashqi funksiya o'zgaruvchilariga ega bo'lish mumkin va bu bazida bu o'zgaruvchilar garbage collector tomonidan yig'ilmasligiga olib keladi,

E’tiboringiz uchun rahmat !

Agarda maqola yoqqan bo'lsa chapak chalish(ko'proq chalsangiz ham bo'ladi) orqali bildiring .