2012-04-02 12 views
5

मैं हमेशा इस धारणा के तहत था कि किसी ऑब्जेक्ट की चाबियाँ स्ट्रिंग के रूप में संग्रहीत की जाती थीं, और कोई भी गैर-स्ट्रिंग मान डाला जाएगा। इसलिए, यह इस धारणा के तहत किया गया है, जबकि कुछ कोड है कि चाबियों का कई हजारों के लिए एक छोटा सा मान संग्रहीत करना पड़ा लेखन, मैं 36 के आधार के लिए सभी कुंजियों परिवर्तित:जावास्क्रिप्ट में संग्रहीत वस्तुओं पर विशेषता नाम कैसे हैं?

// theKey is an integer 
myMap[theKey.toString(36)] = theValue; 

फिर, मैं हूँ कि मेरे इस धारणा को देखने का फैसला किया वास्तव में सही था, और स्मृति उपयोग की जांच करने के लिए क्रोम के प्रोफाइलर का इस्तेमाल किया। यहां पर परीक्षण किए गए परीक्षण और मेमोरी उपयोग:

window.objIntegers = {}; 
for (i = 100000; i--) window.objIntegers[i] = 'a'; 
// 786kb 

window.objStrings = {}; 
for (i = 100000; i--) window.objStrings[i.toString(36)] = 'a'; 
// 16.7mb! 

// and the same pattern but with: 
key = i + .5; // 16.7mb 
key = i + ''; // 786kb 
key = '0' + i; // 16.7mb 
key = i + '0'; // 16.7mb 

जाहिर है, मेरी धारणाएं बंद थीं। हालांकि, मैं क्या सोच रहा हूं, यह है कि वे कैसे संग्रहीत किए जा रहे हैं और क्या यह व्यवहार मानक है, या सिर्फ कुछ अतिरिक्त चाल है जो क्रोमियम/वेबकिट टीम द्वारा जोड़ा गया है?

उत्तर

0

यह क्रोमियम में अनुकूलन है। मेरा मानना ​​है कि इसमें आंतरिक गुणों को स्टोर करने का सबसे प्रभावी तरीका निर्धारित करने के लिए हेरिस्टिक्स (here's one mention of it) है। ईसीएमएस्क्रिप्ट स्क्रिप्ट निर्देशित करता है कि जावास्क्रिप्ट और पर्यावरण के बीच इंटरफ़ेस है और जावास्क्रिप्ट के संपर्क में आने वाली वस्तुओं को आंतरिक रूप से कार्यान्वित करने के बारे में कुछ भी नहीं कहता है।

3

यह वास्तव में वी 8 द्वारा कुछ अतिरिक्त चाल है।

एक JSObject (आंतरिक सी ++ एक जे एस Object का प्रतिनिधित्व), जबकि "properties" जे एस स्ट्रिंग सूचकांक के साथ जिम्मेदार बताते हैं, जिसमें दो गुणधर्म हैं elements और properties, जहां "तत्वों" जे एस संख्यात्मक सूचकांक के साथ जिम्मेदार बताते हैं।

जाहिर है, संख्यात्मक सूचकांक यहां बहुत कम स्मृति का उपभोग करते हैं, क्योंकि संपत्ति के नामों को संग्रहीत करने की आवश्यकता नहीं है। सांख्यिक तत्वों के भंडारण के लिए नामित किया गया गुण के भंडारण के लिए एक, एक और:

http://code.google.com/intl/de-DE/chrome/devtools/docs/memory-analysis-101.html#primitive_objects

एक ठेठ जावास्क्रिप्ट वस्तु दो सरणियों posesses।

यह v8 स्रोत कोड से देखा जा सकता है:

http://code.google.com/p/v8/source/browse/trunk/src/objects.h#1483

// [properties]: Backing storage for properties. 
... 
// [elements]: The elements (properties with names that are integers). 

http://code.google.com/p/v8/source/browse/trunk/src/runtime.cc#4462

MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, 
             Handle<Object> object, 
             Handle<Object> key, 
             Handle<Object> value, 
             PropertyAttributes attr, 
             StrictModeFlag strict_mode) { 
    ... 

    // Check if the given key is an array index. 
    uint32_t index; 
    if (key->ToArrayIndex(&index)) { 
    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 
    // of a string using [] notation. We need to support this too in 
    // JavaScript. 
    // In the case of a String object we just need to redirect the assignment to 
    // the underlying string if the index is in range. Since the underlying 
    // string does nothing with the assignment then we can ignore such 
    // assignments. 
    if (js_object->IsStringObjectWithCharacterAt(index)) { 
     return *value; 
    } 

    Handle<Object> result = JSObject::SetElement(
     js_object, index, value, attr, strict_mode, set_mode); 
    if (result.is_null()) return Failure::Exception(); 
    return *value; 
    } 

    if (key->IsString()) { 
    Handle<Object> result; 
    if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 
     result = JSObject::SetElement(
      js_object, index, value, attr, strict_mode, set_mode); 
    } else { 
     Handle<String> key_string = Handle<String>::cast(key); 
     key_string->TryFlatten(); 
     result = JSReceiver::SetProperty(
      js_object, key_string, value, attr, strict_mode); 
    } 
    if (result.is_null()) return Failure::Exception(); 
    return *value; 
    } 

    // Call-back into JavaScript to convert the key to a string. 
    bool has_pending_exception = false; 
    Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 
    if (has_pending_exception) return Failure::Exception(); 
    Handle<String> name = Handle<String>::cast(converted); 

    if (name->AsArrayIndex(&index)) { 
    return js_object->SetElement(
     index, *value, attr, strict_mode, true, set_mode); 
    } else { 
    return js_object->SetProperty(*name, *value, attr, strict_mode); 
    } 
} 

मैं विस्तार में नहीं जाना होगा, लेकिन ध्यान दें कि SetObjectProperty कॉल या तो कुंजी के आधार पर SetElement या SetProperty। सुनिश्चित नहीं है कि चेक आपके परीक्षण मामले key = i + '0' में क्यों विफल रहता है।

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