मार्क एंड स्वीप (Mark and Sweep) गार्बेज कलेक्शन एल्गोरिदम
यह रेफरेंस-काउंटिंग का सुधार है। "अनावश्यक ऑब्जेक्ट्स" के बजाय "अनपहुंच योग्य (unreachable) ऑब्जेक्ट्स" ढूंढता है।
तीन मुख्य चरण
- रूट (Root): ग्लोबल वेरिएबल्स (ब्राउज़र में
window) से शुरूआत - मार्क फेज: रूट से पहुंच योग्य सभी ऑब्जेक्ट्स को मार्क करें
- स्वीप फेज: अनमार्क्ड (अनपहुंच योग्य) ऑब्जेक्ट्स को मेमोरी से हटाएं
मार्क फेज
// उदाहरण 1: पहुंच योग्य
var obj1 = { prop1: "hello" }; // रूट (window) → obj1 → "hello" → सभी मार्क्ड
// उदाहरण 2: अनपहुंच योग्य बनाना
obj1 = null; // obj1 अब null रेफर करता है
// "hello" वाला ऑब्जेक्ट अब अनपहुंच योग्य → अनमार्क्ड
स्वीप फेज
अनमार्क्ड ऑब्जेक्ट्स (जैसे "hello" वाला ऑब्जेक्ट) को गार्बेज कलेक्टर द्वारा मेमोरी से मुक्त किया जाता है।
साइकिल्स (Cycles) की समस्या हल
रेफरेंस-काउंटिंग में साइकिल्स समस्या थीं, मार्क-एंड-स्वीप में नहीं:
function f() {
var obj1 = {};
var obj2 = {};
obj1.p = obj2; // obj1 रेफर करता है obj2 को
obj2.p = obj1; // obj2 रेफर करता है obj1 को (साइकिल!)
}
f(); // फंक्शन खत्म, दोनों आउट ऑफ स्कोप
// रेफरेंस-काउंटिंग: दोनों का काउंट 1 → कभी कलेक्ट नहीं
// मार्क-एंड-स्वीप: रूट से कोई रास्ता नहीं → दोनों कलेक्ट होंगे ✅
इसे "ट्रेसिंग गार्बेज कलेक्टर" क्यों कहते हैं?
क्योंकि यह रूट से शुरू होकर सभी पहुंच योग्य ऑब्जेक्ट्स को "ट्रेस" (पता लगाता) करता है।
सीमाएं
- नॉन-डिटरमिनिस्टिक: कब चलेगा, प्रिडिक्ट नहीं कर सकते
- मैन्युअल ट्रिगर नहीं: JS में
gc()कॉल नहीं कर सकते - पॉज टाइम: बड़े हीप पर "स्टॉप-द-वर्ल्ड" पॉज हो सकता है
- मेमोरी लीक अभी भी संभव: अनइरादतन ग्लोबल रेफरेंस, क्लोजर्स, डिटैच्ड DOM
आधुनिक इंजन ऑप्टिमाइजेशन्स (V8, SpiderMonkey, आदि)
- जनरेशनल GC: नए/पुराने ऑब्जेक्ट्स अलग-अलग ट्रैक
- इंक्रीमेंटल/कनकरंट: छोटे टुकड़ों में, मेन थ्रेड ब्लॉक किए बिना
- कॉम्पैक्शन: मेमोरी फ्रैगमेंटेशन कम करना
- आइडल-टाइम GC: ब्राउज़र आइडल होने पर चलाना