2013-06-24 8 views
10

DevTools में 'प्रोफाइल' के साथ मेरे ऐप को डिबग करने के दौरान मुझे "अलग डोम पेड़" जमा हुआ। इन अलग-अलग नोड्स में पेड़ को बरकरार रखा गया है जिसमें ज्यादातर checkContext फ़ंक्शन शामिल हैं (sizzle से jQuery - v1.10.1 के अंदर)।jQuery/Sizzle checkContext मेमोरी लीक

Heap snapshot

मुझे यकीन है कि नहीं इस के साथ आगे बढ़ने के लिए कैसे कर रहा हूँ। इस परिणाम का क्या मतलब है?

उत्तर

3

यह वास्तव में एक बग है, सिज़ल को संदर्भ नोड पर लटकने की आवश्यकता नहीं है, यह केवल इसलिए कर रहा है क्योंकि यह अस्थायी चर सेट करने के बाद सफाई नहीं कर रहा है। मैंने issue for it दायर किया, इसे ठीक किया, सभी Sizzle परीक्षण चलाया, और एक पुल अनुरोध किया।

आप jQuery या कड़ाके की धूप के अपने मौजूदा प्रतिलिपि पैच करने के लिए करना चाहते हैं: फ़ाइल

  1. अपने jQuery खोलें या कड़ाके की धूप matcherFromTokens समारोह

  2. के लिए

  3. खोजें यह भीतर इस कोड का पता लगाएं (शीर्ष के पास):

    matchers = [ function(elem, context, xml) { 
        return (!leadingRelative && (xml || context !== outermostContext)) || (
         (checkContext = context).nodeType ? 
          matchContext(elem, context, xml) : 
          matchAnyContext(elem, context, xml)); 
    } ]; 
    
  4. बदलें var rv = को return, और अनाम समारोह के अंत में checkContext = undefined; और फिर return rv; जोड़ने, उदा .:

    matchers = [ function(elem, context, xml) { 
        var ret = (!leadingRelative && (xml || context !== outermostContext)) || (
         (checkContext = context).nodeType ? 
          matchContext(elem, context, xml) : 
          matchAnyContext(elem, context, xml)); 
        // Release the context node (issue #299) 
        checkContext = null; 
        return ret; 
    } ]; 
    

नोट: यह कोड प्रदान करती है checkContext को null क्योंकि जाहिरा तौर पर है कि उनकी शैली है। अगर यह मैं था, तो मैंने इसके बजाय undefined असाइन किया होगा।

यदि पुल अनुरोध/विलय प्रक्रिया के दौरान उठाए गए फ़िक्स के साथ कोई समस्या है, तो मैं उत्तर अपडेट कर दूंगा।

सिज़ल कैश चयनकर्ताओं को देना जारी रखना बेहतर है, क्योंकि jQuery घटना प्रतिनिधिमंडल के साथ संकलित चयनकर्ता सामग्री का उपयोग करता है, और आप वास्तव में यह नहीं चाहते हैं कि प्रत्येक बार प्रासंगिक घटना होने पर मैचर फ़ंक्शंस को पुनर्स्थापित और पुनर्निर्माण करना पड़े। यह पता लगाएं कि तत्व इससे मेल खाते हैं या नहीं।


दुर्भाग्य से संकलित चयनकर्ताओं में तत्वों पर jQuery पर यह एकमात्र जगह नहीं है। प्रत्येक स्थान यह संभवतः एक बग है जो फिक्सिंग का उपयोग कर सकता है।मेरे पास केवल एक दूसरे को ट्रैक करने का समय है, जिसे मैंने रिपोर्ट किया है और तय किया है (खींचने के अनुरोध को लंबित किया गया है):

यदि आप "संभावित रूप से जटिल छद्म" खोज लेंगे तो आपको यह मिल जाएगा :not छद्म चयनकर्ता के लिए:

pseudos: { 
    // Potentially complex pseudos 
    "not": markFunction(function(selector) { 
     // Trim the selector passed to compile 
     // to avoid treating leading and trailing 
     // spaces as combinators 
     var input = [], 
      results = [], 
      matcher = compile(selector.replace(rtrim, "$1")); 

     return matcher[ expando ] ? 
      markFunction(function(seed, matches, context, xml) { 
       var elem, 
        unmatched = matcher(seed, null, xml, []), 
        i = seed.length; 

       // Match elements unmatched by `matcher` 
       while (i--) { 
        if ((elem = unmatched[i])) { 
         seed[i] = !(matches[i] = elem); 
        } 
       } 
      }) : 
      function(elem, context, xml) { 
       input[0] = elem; 
       matcher(input, null, xml, results); 
       return !results.pop(); 
      }; 
    }), 

समस्या सशर्त ऑपरेटर में : के बाद समारोह में है:

function(elem, context, xml) { 
    input[0] = elem; 
    matcher(input, null, xml, results); 
    return !results.pop(); 
}; 

नोट यह कभी नहीं साफ करता है कि input[0] यहां ठीक है:

function(elem, context, xml) { 
    input[0] = elem; 
    matcher(input, null, xml, results); 
    // Don't keep the element (issue #299) 
    input[0] = null; 
    return !results.pop(); 
}; 

मेरे पास वर्तमान में ट्रैक करने का समय है।

+0

तो, आप कह रहे हैं कि केवल मैचर फ़ंक्शन को कैश किया जाना चाहिए था? पूरा नतीजा नहीं? यही कारण है कि मैंने इसकी सूचना नहीं दी है, मैंने सोचा कि सिज़ल उद्देश्य पर डोम नोड्स से मेल खाता है। –

+0

@ कोनराडडविनविन: ठीक है। फंक्शन सरणी वह हिस्सा है जिसे पुन: प्रयोज्य करने की आवश्यकता है। जहां तक ​​मैं कह सकता हूं, 'चेककॉन्टेक्स्ट' केवल एक अस्थायी चर है, जिसका उपयोग किया जाता है ताकि 'matchContext' और' matchAnyContext' तक पहुंच हो, जब उपरोक्त अज्ञात फ़ंक्शन उन्हें कॉल करता है (मुझे लगता है कि यह उन्हें कुछ के लिए पास नहीं कर सकता कारण)। मिलान करने के बाद संदर्भ तत्व को पकड़ने की कोई आवश्यकता नहीं है (और हर आवश्यकता * नहीं *)। मैं वास्तव में आश्चर्यचकित था कि फिक्स इतना आसान था, हालांकि, मैंने सोचा कि हमें इंतजार करना होगा और इसे बाद में साफ़ करना होगा। लेकिन सभी परीक्षण पास होते हैं, इसलिए हम देखेंगे कि यह समीक्षा से बचता है ... –

+0

यह शुद्ध jQuery का उपयोग कर एसपीए ऐप्स के लिए बहुत बड़ा है (jqlite Sizzle का उपयोग नहीं करता है)! महान काम और धन्यवाद! –

5

सिज़ल स्टोर चयनकर्ता कैश में संकलित चयनकर्ताओं, जो डिफ़ॉल्ट रूप से 50 प्रविष्टियों तक स्टोर करता है। आप किसी भी चयन करने से पहले $.expr.cacheLength = 1 सेट करके प्रयोग कर सकते हैं और देख सकते हैं कि वे दूर जाते हैं या नहीं।

यहां दस्तावेज़ https://github.com/jquery/sizzle/wiki/Sizzle-Documentation#-internal-api हैं। आंतरिक लगता है इसलिए वास्तविक उत्पादन कोड में या किसी भी चीज़ पर निर्भर न करें।

+0

धन्यवाद! अलग-अलग नोड्स की 1 कम संख्या में कैश की लंबाई बदलना। यह सुविधा मानक वेबसाइटों के लिए उपयोगी हो सकती है लेकिन यह लंबे समय तक चलने वाले ऐप्स के लिए समझ में नहीं आता है। –

+0

@ कोनराडडज़विनेल मुझे लगता है कि यह बिल्कुल विपरीत है - एक लंबा चलने वाला ऐप उसी चयनकर्ताओं का बार-बार उपयोग करेगा जो कैशिंग से बहुत लाभान्वित होते हैं जबकि एक सामान्य वेबसाइट आम तौर पर केवल एक बार अपने चयनकर्ताओं को चलाती है। यह एक स्मृति रिसाव नहीं है। – Esailija

+1

मैं मानता हूं कि यह एक रिसाव नहीं है - यह नियंत्रित है। हालांकि, हमारे ऐप के मामले में यह एक समस्या है - उपयोगकर्ता अक्सर 'मॉड्यूल' स्विच करते हैं और प्रत्येक मॉड्यूल में बहुत सारे डोम नोड होते हैं। जैसे ही अगला लोड हो जाता है, हम पिछले 'मॉड्यूल' से छुटकारा पाना चाहते हैं। इसके अलावा, हम एक ही चयनकर्ताओं को कई बार कॉल नहीं करते हैं - यह शर्मनाक होगा :) –

संबंधित मुद्दे