2012-04-02 13 views
8

http://jsperf.com/testing-foreach-vs-for-looparray.for देशी पुनरावृत्ति से तेजी से चल रहा है? कैसे?

यह मेरी समझ थी कि टेस्ट केस 2 टेस्ट केस 1 की तुलना में अधिक धीरे-धीरे चलना चाहिए - मैं देखना चाहता था कि कितनी धीमी गति से। जब मैं देखता हूं कि यह अधिक तेज़ी से चलता है तो मेरी आश्चर्य की कल्पना करो!

यहां क्या हो रहा है? दृश्यों के पीछे optimizaiton? या है। क्लीनर और तेज के लिए?

परीक्षण क्रोम 18.0.1025.142 में 32-बिट विंडोज सर्वर पर 2008 R2/7 64-बिट

+1

'forEach' शायद कुछ मूल अनुकूलन या कुछ है। –

+3

और भी, आपको टेस्ट केस 1 में सरणी से मूल्य भी नहीं मिल रहा है, आप 'सरणी [i] ' –

+0

1 के बजाय लॉगिंग कर रहे हैं 1) आपको प्रत्येक परीक्षण पर सरणी नहीं बनाना चाहिए, आप परिभाषित कर सकते हैं वर्र्स जो सभी परीक्षणों पर पहुंच योग्य होंगे 2) आप 'लम्बाई' प्रत्येक लूप – ajax333221

उत्तर

7

कई यात्रा अनुकूलन है कि आपके for पाश जैसे याद आ रही है के होते हैं:

  • कैश सरणी लंबाई
  • पुनरावृति पीछे की ओर
  • उपयोग ++ काउंटर के बजाय काउंटर ++

ये वे हैं जिन्हें मैंने सुना और उपयोग किया है, मुझे यकीन है कि और भी कुछ हैं। अगर स्मृति मुझे सही सेवा प्रदान करती है, तो पीछे की ओर इशारा करते हुए लूप सभी लूपिंग संरचनाओं (अधिकांश ब्राउज़रों में) का सबसे तेज़ है।

कुछ उदाहरणों के लिए this jsperf देखें।

संपादित करें: postfix vs prefix perf test और iterating backwards के लिए लिंक। मैं ++ के बजाय + = 1 का उपयोग करने के लिए अपना संदर्भ नहीं ढूंढ पाया, इसलिए मैंने इसे सूची से हटा दिया है।

+0

मैंने सुना है कि सी ++ के लिए मैं तेज़ हूं तो मैं ++, यह नहीं जानता कि यह जावास्क्रिप्ट –

+0

पर भी पीछे हटता है और '++' के बजाय '+ = 1' का उपयोग करके वास्तव में जेएस में कुछ भी नहीं बदलता है। – kirilloid

+0

@kirilloid + = और ++ दो पूरी तरह से अलग ऑपरेटरों हैं जो अलग-अलग पार्सर कार्यान्वयन में अलग-अलग गति से चल सकते हैं, और बढ़ती बनाम वृद्धि एक प्रसिद्ध माइक्रो-ऑप्टिमाइज़ेशन है। मैं संदर्भ जोड़ने के लिए संपादित करेंगे। – jbabey

0

वे ओपेरा में मेरे लिए लगभग समान हैं। कुछ ध्यान रखना है कि आपके सशर्त() के लिए सरणी है। यदि आप एक चर में सरणी की लंबाई कैश करते हैं, और फिर लूप, तो आपको बेहतर प्रदर्शन देखना चाहिए।

1

प्रत्येक पुनरावृत्ति पर array से length पढ़ना धीमा हो सकता है, लेकिन प्रत्येक के लिए हास्य रूप से धीमा हो सकता है, क्योंकि फ़ंक्शन कॉल जेएस में सस्ता संचालन नहीं है।

पीएस: forEach एफएफ 10 पर 14% धीमी है।

+0

मुझे लगता है कि यह अभी भी मायने रखता है लेकिन मेरा मानना ​​है कि जेआईटी ने फंक्शन कॉल को काफी ज़िप्पीर बनाया है। –

+0

मुझे भी =) विशेष रूप से इसके बाद, मैंने केवल इनलाइनिंग कार्यों के साथ सीपीयू-भारी जेएस कोड ~ 5 बार बढ़ाया। – kirilloid

+0

कोई फर्क नहीं पड़ता कि मैं क्या कोशिश करता हूं, क्योंकि क्रोम में हमेशा हमेशा तेज होता है। – trusktr

0

शायद() धीमा है क्योंकि लूप सरणी की लंबाई प्राप्त करने के लिए प्रत्येक पुनरावृत्ति के लिए 'array.length' लागू होता है।

प्रयास करें:

var nri = array.length; 
for(var i = 0; i < nri; i++){ 
    // ... 
} 
3

अद्यतन:

इन उत्तरों में पुराने चाल का एक बहुत पुराने ब्राउज़र में व्याख्या की जे एस के लिए महान हैं।

किसी भी आधुनिक जेएस कार्यान्वयन में सभी आधुनिक ब्राउज़र, नोड और नवीनतम मोबाइल वेबव्यू समेत, इनलाइन फ़ंक्शंस को वास्तव में जेआईटी (जेएस कंपाइलर) द्वारा कैश किया जा सकता है, जिससे सरणी पुनरावृत्ति के लिए बहुत तेज़ विकल्प होता है। यह विपरीत होता था जहां एक समारोह में कॉल करने के लिए बार-बार एक बिल्ड-अप/टियरडाउन प्रक्रिया की आवश्यकता होती थी जो गैर-तुच्छ पाश के प्रदर्शन को गंभीर रूप से कम कर सकती थी।

सर्वोत्तम प्रदर्शन के लिए मैं किसी भी संदर्भ को संदर्भित करने से बचूंगा जो किसी तर्क के रूप में पारित नहीं किया गया था या यदि आपको ऐसा करने की आवश्यकता नहीं है तो स्वयं को परिभाषित किया गया है। मैं निश्चित रूप से 100% निश्चित नहीं हूं लेकिन मैं देख सकता हूं कि ऐसा क्यों हो सकता है।

गेटर वैल्यू जिसमें सरणी लम्बाई या डोम नोड गुणों की तरह किसी भी प्रकार की लुकअप प्रक्रिया शामिल है, शायद वे भी एक चर के लिए सबसे अच्छा कैश किए गए हैं।

लेकिन उससे परे मैं केवल काम से बचने के बुनियादी सिद्धांत को अपने perf प्रयासों को मार्गदर्शन करने की कोशिश करता हूं। पूर्व-गणना करने वाली चीजें जिन्हें लूप में पुन: गणना करने की आवश्यकता नहीं होती है, या क्वेरी चयनकर्ता को कैशिंग करना अक्सर DOM में rummaging के बजाय var के परिणामस्वरूप होता है। जेआईटी व्यवहार का लाभ उठाने के लिए बहुत मेहनत करने का प्रयास शायद सुंदर आर्केन प्राप्त करने जा रहा है और समय के साथ या सभी जेआईटी में पकड़ने की संभावना नहीं है।

पुराने उत्तर:

ठीक है, पाठ की दीवार भूल जाते हैं। गोली अंक:

var i = someArray.length; //length is cached 
someArray.reverse(); //include this only if iterating in 0-(length-1) order is important 

while(i--){ 
//run a test statement on someArray[i]; 
} 
  • लंबाई कैश किया गया है और तुरंत सूचकांक

  • जे एस AFAIK में पीछे की ओर पुनरावृत्ति दो ऑपरेंड के साथ एक तार्किक ऑपरेटर से परहेज कर रहा है के लाभ में बनाया। इस मामले में हम सिर्फ एक संख्या का मूल्यांकन कर रहे हैं। यह सच है या यह शून्य और झूठा है।

  • मुझे यह भी सुरुचिपूर्ण लगता है।

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