मेमोरी लीक के बारे में

Webman एक स्थायी मेमोरी फ्रेमवर्क है, इसलिए हमें मेमोरी लीक पर थोड़ा ध्यान देना चाहिए। हालाँकि डेवलपरों को अधिक चिंता करने की ज़रूरत नहीं है, क्योंकि मेमोरी लीक बहुत चरम परिस्थितियों में ही होती है और आसानी से टाली जा सकती है। Webman के साथ विकास अनुभव पारंपरिक फ्रेमवर्क से मूलतः समान है; अतिरिक्त मेमोरी प्रबंधन संचालन की आवश्यकता नहीं है।

सुझाव
Webman में अंतर्निहित monitor प्रक्रिया सभी प्रक्रियाओं की मेमोरी उपयोग की निगरानी करती है। जब किसी प्रक्रिया की मेमोरी उपयोग php.ini में memory_limit पर सेट मान तक पहुँचने वाली होती है, तो संबंधित प्रक्रिया मेमोरी मुक्त करने के लिए स्वचालित रूप से सुरक्षित तरीके से पुनः आरंभ हो जाती है; एप्लिकेशन पर कोई प्रभाव नहीं पड़ता।

मेमोरी लीक की परिभाषा

अनुरोधों के साथ webman की मेमोरी उपयोग बढ़ना सामान्य बात है। सामान्यतः जब कोई प्रक्रिया एक निश्चित अनुरोध मात्रा (आमतौर पर लाखों में) तक पहुँचती है, तो मेमोरी बढ़ना रुक जाता है या कभी-कभार थोड़ा बढ़ता है।

अधिकांश एप्लिकेशनों में एकल प्रक्रिया की मेमोरी उपयोग अंततः लगभग 10M–100M पर स्थिर हो जाती है। एकल प्रक्रिया मेमोरी 100M से अधिक नहीं होने तक चिंता करने की ज़रूरत नहीं है।

इसके अलावा, बड़ी फ़ाइलें, बड़े अनुरोध संसाधित करते या डेटाबेस से बड़ी मात्रा में डेटा पढ़ते समय PHP बहुत मेमोरी आवंटित करता है। PHP इस मेमोरी का कुछ हिस्सा पुनः उपयोग के लिए रख सकता है और ऑपरेटिंग सिस्टम को सब कुछ वापस नहीं कर सकता; इससे मेमोरी उपयोग अधिक दिखता है। चूंकि मेमोरी पुनः उपयोग होती है, चिंता की बात नहीं है।

सुझाव
phar या बाइनरी पैक प्रोजेक्ट में, अगर पैकेज का आकार बड़ा है तो मेमोरी उपयोग का 100M से अधिक होना सामान्य है।

मेमोरी लीक की पुष्टि कैसे करें

अगर किसी प्रक्रिया ने दस लाख से अधिक अनुरोध संसाधित किए हैं, मेमोरी 100M से अधिक है, और हर अनुरोध के बाद भी मेमोरी बढ़ रही है, तो मेमोरी लीक हो सकती है।

मेमोरी लीक कैसे खोजें

एक सरल तरीका प्रत्येक API पर तनाव परीक्षण करके पता करना है कि दस लाख अनुरोधों के बाद भी कौन सा API मेमोरी उपयोग बढ़ाता रहता है।

समस्या वाला API मिलने के बाद बाइनरी सर्च विधि इस्तेमाल करें: हर बार व्यावसायिक कोड का आधा हिस्सा कमेंट करते रहें जब तक समस्या वाला कोड पता न चले।

मेमोरी लीक कैसे होती है

मेमोरी लीक तभी होती है जब निम्नलिखित दोनों शर्तें पूरी हों:

  1. लंबे जीवनचक्र वाला एरे मौजूद हो (सामान्य एरे समस्या नहीं है)
  2. और यह लंबे जीवनचक्र वाला एरे असीमित रूप से बढ़ता जाए (एप्लिकेशन लगातार डेटा डालता रहे, कभी साफ़ न करे)

दोनों शर्तें पूरी होने पर ही लीक होती है। यदि कोई शर्त पूरी न हो या सिर्फ एक पूरी हो तो लीक नहीं है।

लंबे जीवनचक्र वाले एरे

Webman में लंबे जीवनचक्र वाले एरे में शामिल हैं:

  1. static कीवर्ड वाले एरे
  2. सिंगलटन के एरे प्रॉपर्टी
  3. global कीवर्ड वाले एरे

ध्यान दें
Webman में लंबे जीवनचक्र डेटा के उपयोग की अनुमति है, लेकिन यह सुनिश्चित करना चाहिए कि डेटा सीमित है और तत्वों की संख्या असीमित रूप से न बढ़े।

प्रत्येक मामले के उदाहरण नीचे दिए गए हैं।

असीमित रूप से बढ़ने वाला static एरे

class Foo
{
    public static $data = [];
    public function index(Request $request)
    {
        self::$data[] = time();
        return response('hello');
    }
}

static कीवर्ड से परिभाषित $data एरे लंबे जीवनचक्र वाला है। उदाहरण में $data हर अनुरोध के साथ बढ़ता रहता है, जिससे मेमोरी लीक होती है।

असीमित रूप से बढ़ने वाली सिंगलटन एरे प्रॉपर्टी

class Cache
{
    protected static $instance;
    public $data = [];

    public function instance()
    {
        if (!self::$instance) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    public function set($key, $value)
    {
        $this->data[$key] = $value;
    }
}

कॉल कोड

class Foo
{
    public function index(Request $request)
    {
        Cache::instance()->set(time(), time());
        return response('hello');
    }
}

Cache::instance() एक Cache सिंगलटन लौटाता है जो लंबे जीवनचक्र वाला क्लास इंस्टैंस है। हालाँकि इसकी $data प्रॉपर्टी static कीवर्ड प्रयोग नहीं करती, लेकिन चूंकि क्लास स्वयं लंबे जीवनचक्र वाली है, इसलिए $data भी लंबे जीवनचक्र वाला एरे है। अलग-अलग कुंजी वाले डेटा लगातार $data एरे में जोड़ने पर प्रोग्राम की मेमोरी उपयोग बढ़ती है और लीक होती है।

ध्यान दें
अगर Cache::instance()->set(key, value) से जोड़ी गई कुंजियाँ सीमित संख्या में हैं तो लीक नहीं होगी, क्योंकि $data एरे असीमित रूप से नहीं बढ़ता।

असीमित रूप से बढ़ने वाला global एरे

class Index
{
    public function index(Request $request)
    {
        global $data;
        $data[] = time();
        return response($foo->sayHello());
    }
}

global कीवर्ड से परिभाषित एरे फ़ंक्शन या क्लास मेथड पूर्ण होने के बाद रिसाइकल नहीं होते, इसलिए लंबे जीवनचक्र वाले हैं। उपरोक्त कोड अनुरोध बढ़ने के साथ मेमोरी लीक पैदा करता है। इसी तरह फ़ंक्शन या मेथड के अंदर static कीवर्ड से परिभाषित एरे भी लंबे जीवनचक्र वाले होते हैं; अगर एरे असीमित रूप से बढ़ता है तो लीक होती है, उदाहरण के लिए:

class Index
{
    public function index(Request $request)
    {
        static $data = [];
        $data[] = time();
        return response($foo->sayHello());
    }
}

सुझाव

डेवलपरों को मेमोरी लीक पर विशेष ध्यान देने की सलाह नहीं दी जाती, क्योंकि यह कम ही होती है। हो जाए तो तनाव परीक्षण से लीक पैदा करने वाला कोड ढूँढ़ा जा सकता है। डेवलपर लीक बिंदु न ढूँढ़ पाए तो भी webman का अंतर्निहित monitor सेवा समय पर मेमोरी लीक वाली प्रक्रिया को सुरक्षित रूप से पुनः आरंभ करके मेमोरी मुक्त कर देता है।

मेमोरी लीक जितना हो सके टालना चाहते हैं तो इन सुझावों पर ध्यान दे सकते हैं:

  1. global और static कीवर्ड वाले एरे जितना संभव न इस्तेमाल करें; इस्तेमाल करें तो सुनिश्चित करें कि असीमित रूप से न बढ़ें।
  2. अपरिचित क्लास के लिए सिंगलटन की जगह new कीवर्ड से इनिशियलाइज़ करें। सिंगलटन ज़रूरी हो तो देखें कि उसमें असीमित रूप से बढ़ने वाली एरे प्रॉपर्टी तो नहीं है।