गिरफ्तारी = [] गिरफ्तारी की तुलना में तेज है = नया एरियर?


146

मैंने इस कोड को चलाया और नीचे का परिणाम मिला। मैं यह जानने के लिए उत्सुक हूं कि []तेज क्यों है?

console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')

console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
  • का उपयोग कर []: 299ms
  • का उपयोग कर new: 363ms

रेन्नोस के लिए धन्यवाद इस कोड का एक बेंचमार्क है और एक चर को परिभाषित करने के लिए कुछ और संभव तरीका है।

यहाँ छवि विवरण दर्ज करें


5
आपको jsperf में दिलचस्पी हो सकती है ।
इंगित


कीवर्ड को नए नोट करें। इसका मतलब है "कृपया कम कुशल हो"। यह कभी समझ में नहीं आता है, और ब्राउज़र को अनुकूलन करने की कोशिश करने के बजाय सामान्य इंस्टेंटेशन करने की आवश्यकता होती है।
बीटगैमेट

2
@kinakuta नहीं। वे दोनों नई गैर-समान वस्तुएं बनाते हैं। मैं मतलब []के बराबर है new Array(), स्रोत कोड के मामले में प्रपत्र भाव लौटे वस्तुओं नहीं
Raynos

1
हां, यह बहुत महत्वपूर्ण नहीं है। लेकिन मुझे जानना पसंद है।
मोहसिन

जवाबों:


195

पिछले उत्तरों पर और विस्तार ...

एक सामान्य संकलक परिप्रेक्ष्य और वीएम-विशिष्ट अनुकूलन की अवहेलना से:

सबसे पहले, हम लेक्सिकल विश्लेषण चरण से गुजरते हैं जहां हम कोड को टोकन करते हैं।

उदाहरण के अनुसार, निम्नलिखित टोकन का उत्पादन किया जा सकता है:

[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)

उम्मीद है कि यह आपको एक पर्याप्त दृश्य प्रदान करेगा ताकि आप समझ सकें कि कितना (या कम) प्रसंस्करण की आवश्यकता है।

  1. उपरोक्त टोकन के आधार पर, हम एक तथ्य के रूप में जानते हैं कि ARRAY_INIT हमेशा एक सरणी का उत्पादन करेगा। इसलिए हम केवल एक सरणी बनाते हैं और उसे आबाद करते हैं। जहाँ तक अस्पष्टता है, लेक्सिकल विश्लेषण चरण ने पहले ही ARRAY_INIT को एक ऑब्जेक्ट प्रॉपर्टी एक्सेसर (जैसे obj[foo]) या स्ट्रिंग्स / रेगेक्स शाब्दिक (जैसे "फू [] बार" या /] / /) के अंदर ब्रैकेट से अलग कर दिया है।

  2. यह छोटा है, लेकिन हमारे पास और भी टोकन हैं new Array। इसके अलावा, यह पूरी तरह से अभी तक स्पष्ट नहीं है कि हम केवल एक सरणी बनाना चाहते हैं। हम "नया" टोकन देखते हैं, लेकिन "नया" क्या? फिर हम IDENTIFIER टोकन देखते हैं जो दर्शाता है कि हम एक नया "ऐरे" चाहते हैं, लेकिन जावास्क्रिप्ट वीएम आमतौर पर "देशी वैश्विक वस्तुओं" के लिए एक आईडी टोकन और टोकन को अलग नहीं करता है। इसलिए ...

  3. जब भी हम एक IDENTIFIER टोकन का सामना करते हैं, तो हमें गुंजाइश श्रृंखला को देखना होगा। जावास्क्रिप्ट वीएम में प्रत्येक निष्पादन संदर्भ के लिए एक "सक्रियण ऑब्जेक्ट" होता है जिसमें "तर्क" ऑब्जेक्ट, स्थानीय रूप से परिभाषित चर आदि शामिल हो सकते हैं। यदि हम इसे सक्रियण ऑब्जेक्ट में नहीं पा सकते हैं, तो हम गुंजाइश श्रृंखला की तलाश शुरू करते हैं जब तक हम वैश्विक दायरे तक नहीं पहुंच जाते। । अगर कुछ नहीं मिला, तो हम एक फेंक देते हैं ReferenceError

  4. एक बार जब हम परिवर्तनशील घोषणा को स्थित कर लेते हैं, तो हम निर्माणकर्ता को आमंत्रित करते हैं। new Arrayएक अंतर्निहित फ़ंक्शन कॉल है, और अंगूठे का नियम यह है कि फ़ंक्शन कॉल निष्पादन के दौरान धीमे होते हैं (इसलिए स्थैतिक C / C ++ कंपाइलर "फ़ंक्शन इनलाइनिंग" की अनुमति देते हैं - जो कि जेएस जेआईटी इंजन जैसे स्पाइडरमोंकी को ऑन-द-फ्लाई करना है)

  5. Arrayनिर्माता ओवरलोड हो गया है। ऐरे कंस्ट्रक्टर को देशी कोड के रूप में लागू किया जाता है, इसलिए यह कुछ प्रदर्शन संवर्द्धन प्रदान करता है, लेकिन इसके लिए अभी भी तर्क की लंबाई की जांच करना और उसके अनुसार कार्य करना होगा। इसके अलावा, घटना में केवल एक तर्क की आपूर्ति की जाती है, हमें आगे तर्क के प्रकार की जांच करने की आवश्यकता है। नया ऐरे ("फू") पैदा करता है ["फू"] जहां नया ऐरे (1) पैदा करता है [अपरिभाषित]

तो यह सब आसान करने के लिए: सरणी शाब्दिक के साथ, VM जानता है कि हम एक सरणी चाहते हैं; इसके साथ new Array, वीएम को अतिरिक्त सीपीयू चक्र का उपयोग करने की जरूरत है ताकि यह पता लगाया जा सके कि new Array वास्तव में क्या करता है।


एक = नया ऐरे (1000) नहीं है; (0 से 999 तक) {[i] = i} से तेज = = [] के लिए (0 से 999 तक) {[i] = i} के कारण हालांकि ओवरहेड आवंटन?
वाई। योशी

बस एक टेस्ट केस कर दिया। new Array (n) उन मामलों में तेज़ है जहाँ आप समय से पहले सरणी का आकार जानते हैं jsperf.com/square-braces-vs-new-array
Y. Yoshii

27

एक संभावित कारण यह है कि new Arrayनाम देखने की आवश्यकता होती है Array(आप उस नाम के साथ एक चर गुंजाइश में हो सकते हैं), जबकि []ऐसा नहीं है।


4
तर्कों की जाँच भी योगदान दे सकती है।
लियोनिद

Arrayएक तर्क lenऔर एक से अधिक तर्क दोनों को स्वीकार करता है। जहां []केवल कई तर्कों को स्वीकार किया जाता है। इसके अलावा फ़ायरफ़ॉक्स परीक्षण लगभग कोई अंतर नहीं दिखाते हैं।
Raynos

मुझे लगता है कि इसमें कुछ सच्चाई है। IIFE में ओपी के लूप टेस्ट को चलाने से प्रदर्शन पर एक (अपेक्षाकृत) पर्याप्त प्रभाव पड़ता है। सहित परीक्षण var Array = window.Arrayके प्रदर्शन में सुधार new Array
user113716

मुझे नहीं लगता कि यह सही है क्योंकि यह कंसोल.टाइम ('अधिक vars new'); के लिए (var i = 0; मैं <200000; i ++) {var arr = new Array ()}; कंसोल.टाइम ईएंड ('अधिक vars new'); अधिक vars नया: 390ms और यह कंसोल.टाइम ('अधिक vars new'); var myOtherObject = {}, myOtherArray = []; के लिए (var i = 0; मैं <200000; i ++) {var arr = new Array ()}; कंसोल.टाइम ईएंड ('अधिक vars new'); अधिक नए वार्स: 369ms एक ही समय देता है
मोहसिन

2

अच्छा प्रश्न। पहला उदाहरण एक सरणी शाब्दिक कहा जाता है। यह कई डेवलपर्स के बीच सरणियाँ बनाने का पसंदीदा तरीका है। यह हो सकता है कि प्रदर्शन अंतर नए ऐरे () कॉल के तर्कों की जाँच करने और फिर ऑब्जेक्ट बनाने के कारण होता है, जबकि शाब्दिक सीधे एक सरणी बनाता है।

प्रदर्शन में अपेक्षाकृत छोटा अंतर इस बिंदु का समर्थन करता है जो मुझे लगता है। आप जिस तरह से वस्तु और वस्तु शाब्दिक {} के साथ एक ही परीक्षण कर सकते हैं।


1

यह कुछ समझ में आता है

ऑब्जेक्ट्स शाब्दिक हमें कोड लिखने में सक्षम बनाते हैं जो बहुत सारी सुविधाओं का समर्थन करता है फिर भी यह हमारे कोड के कार्यान्वयनकर्ताओं के लिए अपेक्षाकृत सरल है। कार्यों आदि के लिए दिए गए तर्कों का सही क्रम बनाए रखने या बनाए रखने की आवश्यकता नहीं है।

http://www.dyn-web.com/tutorials/obj_lit.php


1

इसके अलावा, दिलचस्प है, अगर सरणी की लंबाई अग्रिम में ज्ञात है (तत्वों को निर्माण के ठीक बाद जोड़ा जाएगा), एक निर्दिष्ट लंबाई के साथ एक सरणी निर्माता का उपयोग हाल के Google Chrome 70+ पर बहुत तेज है

  • " नया ऐरे ( % ARR_LENGTH% ) " - 100% (तेज) !

  • " [] " - 160-170% (धीमा)

उपायों के परिणामों के साथ चार्ट।

परीक्षण यहाँ पाया जा सकता है - https://jsperf.com/small-arr-init-with-ogn-length-brackets-vs-new-array/2

नोट: यह परिणाम Google Chrome v.70 + पर परीक्षण किया गया ; में फ़ायरफ़ॉक्स v.70 और IE दोनों लगभग बराबर वेरिएंट।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.