JavaScriptda xotira boshqaruvi(Garbage Collection)
JavaScript-da xotira boshqaruvi avtomatik ravishda amalga oshiriladi va bu jarayon biz uchun ko'rinmasdir. Biz primitivlar, obyektlar, funksiyalar yaratamiz... Bularning barchasi xotira talab qiladi.
Garbage Collection
JavaScript-da xotira boshqaruvi avtomatik ravishda amalga oshiriladi va bu jarayon biz uchun ko'rinmasdir. Biz primitivlar, obyektlar, funksiyalar yaratamiz... Bularning barchasi xotira talab qiladi.
Nimadir kerak bo'lmay qolganda nima sodir bo'ladi? JavaScript dvigateli buni qanday aniqlaydi va xotirani qanday tozalaydi?
Kirish mumkinlik
JavaScript-da xotira boshqaruvining asosiy konsepsiyasi kirish mumkinlik (reachability) hisoblanadi.
Oddiy qilib aytganda, “kirish mumkin” qiymatlar qandaydir tarzda kirish mumkin bo‘lgan yoki foydalanilishi mumkin bo‘lgan qiymatlardir. Ular xotirada saqlanishi kafolatlanadi.
Kirishi mumkin bo'lgan qiymatlarning asosiy to'plami mavjud bo'lib, ularni yo'q qilish mumkin emasligi aniq sabablarga ko'ra amalga oshirilmaydi.
Masalan:
- Hozirda bajarilayotgan funksiya, uning lokal o'zgaruvchilari va parametrlari.
- Joriy chaqiriqlar zanjiridagi boshqa funksiyalar, ularning lokal o'zgaruvchilari va parametrlari.
- Global o'zgaruvchilar.
- (yana ba'zi boshqa ichki qiymatlar ham mavjud)
Ushbu qiymatlar "ildizlar" deb ataladi.
Ildizdan havola yoki havolalar zanjiri orqali kirish mumkin bo'lsa, har qanday boshqa qiymat kirish mumkin deb hisoblanadi.
Masalan, agar global o'zgaruvchida obyekt bo'lsa va bu obyekt boshqa obyekti ko'rsatadigan xususiyatga ega bo'lsa, bu obyekt kirish mumkin deb hisoblanadi. Va u ko'rsatadigan obyektlar ham kirish mumkin bo'ladi. Bunga misollar quyida keltiriladi.
JavaScript dvigatelida fon jarayoni mavjud bo'lib, u "garbage collector" deb ataladi. U barcha obyektlarni kuzatib boradi va kirish mumkin bo'lmagan obyektlarni olib tashlaydi.
Oddiy misol
Mana eng oddiy misol:
Bu erda o'q obyektga havolani ko'rsatadi. Global o'zgaruvchi user
{name: "John"}
obyektiga havola qiladi (qisqacha John deb ataymiz). Johnning "name" xususiyati primitiv qiymatni saqlaydi, shuning uchun u obyekt ichida tasvirlangan.
Agar user
qiymati qayta yozilsa, havola yo'qoladi:
Endi John kirish mumkin bo'lmaydi. Uni kirishning hech qanday usuli yo'q, unga hech qanday havola yo'q. Garbage collector ma'lumotlarni yo'q qiladi va xotirani bo'shatadi.
Ikki havola
Endi user
dan admin
ga havolani nusxa ko'chirganimizni tasavvur qilaylik:
Endi xuddi shunday qilsak:
...Unda obyekt hali ham admin
global o'zgaruvchisi orqali kirish mumkin bo'ladi, shuning uchun u xotirada qolishi kerak. Agar admin
ni ham qayta yozsak, unda u ham olib tashlanadi.
O'zaro bog'langan obyektlar
Endi murakkabroq misol. Oila:
marry
funksiyasi ikki obyektni o'zaro havolalar orqali "nikohlantiradi" va ularni o'z ichiga olgan yangi obyektni qaytaradi.
Hosil bo'lgan xotira tuzilishi:
Hozirda barcha obyektlar kirish mumkin.
Endi ikkita havolani olib tashlaymiz:
Faqat bitta ushbu ikkita havolani o'chirish yetarli emas, chunki barcha obyektlar hali ham kirish mumkin bo'lardi.
Ammo agar ikkisini ham o'chirsak, John endi kirish mumkin bo'lmay qoladi, chunki unga hech qanday kiruvchi havola yo'q:
Chiquvchi havolalar muhim emas. Faqat kiruvchi havolalar obyektni kirish mumkin qilishi mumkin. Shunday qilib, John endi kirish mumkin bo'lmaydi va uning barcha ma'lumotlari bilan birga xotiradan o'chiriladi.
Kirish mumkin bo'lmagan orol
Butun bir o'zaro bog'langan obyektlar oroli kirish mumkin bo'lmay qolishi va xotiradan olib tashlanishi mumkin.
Manba obyekt yuqoridagi bilan bir xil. Keyin:
Xotiradagi rasm quyidagicha bo'ladi:
Bu misol kirish mumkinlik konsepsiyasining qanchalik muhimligini ko'rsatadi.
John va Ann hali ham bog'langan, ikkalasi ham kiruvchi havolalarga ega ekanligi aniq. Lekin bu yetarli emas.
Ilgari family
obyekt ildizidan uzildi, endi unga hech qanday havola yo'q, shuning uchun butun orol kirish mumkin bo'lmaydi va olib tashlanadi.
Ichki algoritmlar
Asosiy garbage collection algoritmi “belgilash-va-tozalash” (mark-and-sweep) deb ataladi.
Quyidagi “garbage collection” bosqichlari muntazam ravishda bajariladi:
- Garbage collector ildizlarni oladi va ularni "belgilaydi" (eslab qoladi).
- Keyin u ularning barcha havolalarini ko'rib chiqadi va belgilaydi.
- Keyin belgilangan obyektlarni ko'rib chiqadi va ularning havolalarini belgilaydi. Barcha tashrif buyurilgan obyektlar eslab qolingan bo'ladi, shuning uchun kelajakda bir xil obyekti ikki marta ko'rib chiqilmaydi.
- …Va bu jarayon barcha kirish mumkin bo'lgan (ildizlardan) havolalar tashrif buyurilguniga qadar davom etadi.
- Belgilanganlardan tashqari barcha obyektlar olib tashlanadi.
Misol uchun, obyektlar tuzilmasi quyidagicha bo'lsin:
Biz aniq ko'rishimiz mumkin bo'lgan "kirish mumkin bo'lmagan orol" o'ng tomonda. Endi “belgilash-va-tozalash” garbage collectori uni qanday hal qilishini ko'rib chiqamiz.
Birinchi bosqich ildizlarni belgilaydi:
Keyin ularning havolalariga ergashib, havola qilingan obyektlarni belgilaymiz:
…Va imkon qadar keyingi havolalarni kuzatishda davom etamiz:
Endi bu jarayonda tashrif buyurilmagan obyektlar kirish mumkin bo'lmagan deb hisoblanadi va olib tashlanadi:
Biz bu jarayonni ildizlardan katta bo'yoq paqirini to'kib, barcha havolalar orqali oqib o'tayotganini va barcha kirish mumkin bo'lgan obyektlarni belgilayotganini tasavvur qilishimiz mumkin. Belgilanmaganlari keyin olib tashlanadi.
Bu garbage collection qanday ishlashining konsepsiyasidir. JavaScript dvigatellari uni tezroq ishlatish va kodni bajarishda kechikishlarni kiritmaslik uchun ko'plab optimallashtirishlarni qo'llaydi.
Ba'zi optimallashtirishlar:
- Avlodlar bo'yicha yig'ish – obyektlar ikki to'plamga bo'linadi: "yangi" va "eski". Oddiy kodda ko'plab obyektlar qisqa umr ko'radi: ular paydo bo'ladi, o'z ishini bajaradi va tezda "o'ladi", shuning uchun yangi obyektlarni kuzatib borish va xotirani tozalash mantiqiydir. Ular yetarlicha uzoq yashasa, "eski" bo'lib, kamroq tekshiriladi.
- Bosqichma-bosqich yig'ish – agar ko'plab obyektlar mavjud bo'lsa va biz bir vaqtning o'zida barcha obyektlarni belgilash va tekshirishga harakat qilsak, bu vaqt talab qilishi va bajarilishida sezilarli kechikishlarni kiritishi mumkin. Shunday qilib, dvigatel mavjud obyektlar to'plamini bir nechta qismga bo'ladi. Va keyin bu qismlarni birma-bir tozalaydi. Katta yig'ish o'rniga ko'plab kichik garbage collectionlar mavjud. Bu yig'
ishlar orasida o'zgarishlarni kuzatish uchun qo'shimcha qaydlar talab qiladi, lekin biz katta kechikish o'rniga ko'plab kichik kechikishlarga ega bo'lamiz.
- Bo'sh vaqt yig'ish – garbage collector CPU bo'sh turganda faqat ishlashga harakat qiladi, bu bajarishga ta'sirini kamaytirish uchun.
Boshqa optimallashtirishlar va garbage collection algoritmlarining turli xil versiyalari mavjud. Bularni bu yerda tavsiflash juda qiziqarli bo'lsa-da, turli dvigatellar turli xil o'zgarishlar va usullarni amalga oshiradi, shuning uchun ularni chuqurroq o'rganish hojat bo'lmasligi mumkin. Albatta, bu sof qiziqish masalasi bo'lmasa. Agar shunday bo'lsa, quyida ba'zi havolalar beriladi.
Xulosa
Asosiy bilishingiz kerak bo'lgan narsalar:
- Garbage collection avtomatik ravishda amalga oshiriladi. Biz uni majburlay olmaymiz yoki oldini olmaymiz.
- Obyektlar xotirada saqlanadi, ular kirish mumkin bo'lsa.
- Havola qilingan obyekt ildizdan kirish mumkin bo'lmasligi mumkin: o'zaro bog'langan obyektlar to'plami butunligicha kirish mumkin bo'lmay qolishi mumkin, yuqoridagi misolda ko'rganimizdek.
- Zamonaviy dvigatellar garbage collectionning ilg'or algoritmlarini amalga oshiradi.
"Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones va boshqalar) kabi umumiy kitob ba'zi birlarini qamrab oladi.
Agar past darajadagi dasturlash bilan tanish bo'lsangiz, V8 garbage collector haqida ko'proq ma'lumotni "A tour of V8: Garbage Collection" maqolasida topishingiz mumkin.
V8 blogi vaqti-vaqti bilan xotira boshqaruviga oid maqolalarni nashr etadi. Tabiiyki, garbage collection haqida ko'proq bilishni istasangiz, V8 ichki qismlarini umumiy o'rganish va V8 muhandislaridan biri bo'lgan Vyacheslav Egorovning blogini o'qish yaxshiroq bo'ladi. “V8”ni tilga olayotganim sababi, u internetdagi maqolalarda yaxshi yoritilgan. Boshqa dvigatellarda ko'plab yondashuvlar o'xshash bo'lsa-da, garbage collection ko'p jihatdan farq qiladi.
Dvigatellarni chuqur bilish past darajadagi optimallashtirishlarga muhtoj bo'lganda foydali bo'ladi. Bu til bilan tanishganingizdan keyin rejalashtirishda oqilona bo'lar edi.