जावास्क्रिप्ट में सरणी के माध्यम से लूप का सबसे तेज़ तरीका क्या है?


249

मैंने उन किताबों से सीखा है जिन्हें आपको इस तरह से लिखना चाहिए you

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

इसलिए arr.lengthहर बार गणना नहीं की जाएगी।

दूसरों का कहना है कि संकलक इसके लिए कुछ अनुकूलन करेंगे, ताकि आप बस लिख सकें:

for(var i=0; i < arr.length; i++){
    // blah blah
}

मैं सिर्फ यह जानना चाहता हूं कि व्यवहार में सबसे अच्छा तरीका कौन सा है?


1
: भी लायक एक नज़र जब साथ सरणी पाशन निपटने jsperf.com/array-loop-var-caching
cloakedninjas

@ wong2 ब्राउज़रडिट से Tthis बेंचमार्क में विकल्पों का एक अधिक पूर्ण संग्रह है।
डोमी


पिछले जेस्बेन में सुधार: jsben.ch/#/R6LbS
कॉर्बफ़न

क्या हम for ... ofइस प्रतियोगिता में लूप का परिचय दे सकते हैं ? वाक्यविन्यास और भी आसान लगता है, कैशिंग के बिना लूप के लिए, और मैं जानना चाहता हूं कि क्या मुझे लूप का उपयोग करने के लिए स्विच करना चाहिए।
प्रोग्रामरराज

जवाबों:


339

अधिकांश आधुनिक ब्राउज़रों के साथ यह परीक्षण करने के बाद ...

http://jsben.ch/dyM52

वर्तमान में , लूप का सबसे तेज़ रूप (और मेरी राय में सबसे अधिक स्पष्ट रूप से स्पष्ट है)।

लंबाई कैशिंग के साथ लूप के लिए एक मानक

for (var i = 0, len = myArray.length; i < len; i++) {

}

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


6
दिलचस्प बात यह है कि IE9 में यह तेज है: (var i = 0, len = myArray.length = <len; ++ i) {} // उपसर्ग incr, पोस्टफिक्स के बजाय
क्रिस्टोफर बेन्नेज

4
उपयोग करने के अन्य कारणों के लिए पोस्टफ़िक्स पर उपसर्ग ऑपरेटरों को प्राथमिकता दें देखें ++i
बेनेट McElwee

4
मैंने उपसर्ग ऑपरेटर का उपयोग करके परीक्षण किया क्योंकि @BennettMcElwee ने सुझाव दिया और यह थोड़ा तेज़ चलता है: jsperf.com/caching-array-length/84for(var i=0, len=myArray.length; i<len; ++i)
4:22 पर विस्मो

21
आपको इस लूप का उपयोग करके सावधान रहना होगा। मैंने इसका उपयोग करना शुरू कर दिया और एक गलती की वजह से बग को ट्रैक करना मुश्किल था। यदि आप इस तरह दो छोरों को घोंसला देते हैं: jsfiddle.net/KQwmL/1 । आपको दो छोरों में भिन्न रूप से var len का नाम रखने के लिए सावधान रहना होगा, अन्यथा दूसरा लूप पहली लेन को अधिलेखित कर देगा।
रुई मार्केस

6
@IllshawMedia आप एक varबयान के साथ कई चर घोषित कर सकते हैं । यह कैसे लिखा जाता है, lenजैसा कि आप सुझाव देते हैं , वास्तव में स्कूप किया गया है।
जॉन्डवीडजोन

90

जावास्क्रिप्ट ऐरे के माध्यम से लूप बनाने का सबसे तेज़ तरीका है:

var len = arr.length;
while (len--) {
    // blah blah
}

पूर्ण तुलना के लिए http://blogs.oracle.com/greimer/entry/best_way_to_code_a देखें


1
var( lenएक वैश्विक चर बन जाता है) का उपयोग करने के लिए मत भूलना । इसके अलावा, अधिक लूप बेंचमार्क के लिए jsperf.com/loops देखें ।
मैथियास ब्येनेंस

22
इस उत्तर पर आधारित ब्लॉग पोस्ट अब लगभग 4 साल पुराना है, और उस समय में js इंजन में बहुत कुछ बदल गया है, एक अद्यतन तुलना के लिए मेरा जवाब नीचे देखें।
jondavidjohn

1
मैं @jondavidjohn से सहमत हूँ। मैंने इस कोड का परीक्षण किया और यह कम कुशल निकला ... चेक jsperf.com/caching-array-length/84
winmo

उपरोक्त उत्तर लगभग सार्वभौमिक (ब्राउज़रों के पार) फॉर-लूप की तुलना में बहुत धीमा है। स्वीकृत उत्तर में JSPerf लिंक देखें। यह बहुत शर्म की बात है, क्योंकि यह बेहद पठनीय आईएमओ है।
लेटेरियन

3
Im @jondavidjohn अनुमान लगा रहा है कि 'मेरे जवाब के नीचे' से आपका क्या तात्पर्य है, 'मेरा जवाब' ऊपर है।
शनिमल

40

जून 2016 तक , नवीनतम क्रोम में कुछ परीक्षण करना (मई 2016 में ब्राउज़र बाजार का 71%, और बढ़ता हुआ):

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

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

  • यदि आपका ऐप बहुत सारे आइटम पर प्रसारित होता है या आपका लूप कोड एक फ़ंक्शन के अंदर होता है जो अक्सर उपयोग किया जाता है, तो लूप के लिए एक सीधा उत्तर है:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • यदि आपका ऐप वास्तव में बहुत सारी वस्तुओं के माध्यम से पुनरावृत्त नहीं होता है या आपको बस यहां और वहां छोटे पुनरावृत्तियों को करने की आवश्यकता है, तो मानक forEach कॉलबैक या अपनी पसंद के जेएस लाइब्रेरी से किसी भी समान फ़ंक्शन का उपयोग करने से त्रुटियों को अधिक समझ में आ सकता है और कम त्रुटियों का खतरा हो सकता है, क्योंकि इंडेक्स वैरिएबल स्कोप बंद हो गया है और आपको कोष्ठक का उपयोग करने की आवश्यकता नहीं है, सीधे ऐरे मान को एक्सेस करते हुए:

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
  • यदि आपको वास्तव में अरबों पंक्तियों पर पुनरावृत्ति करते समय कुछ मिलीसेकंड खरोंच करने की आवश्यकता होती है और आपके सरणी की लंबाई प्रक्रिया के माध्यम से नहीं बदलती है, तो आप अपने लूप के लिए लंबाई को कैशिंग करने पर विचार कर सकते हैं। हालांकि मुझे लगता है कि यह आजकल जरूरी नहीं है:

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }

नहीं। jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 दिखाता है कि सबसे तेज़ "रिवर्स लूप, निहित तुलना, इनबिल्ड कोड" (105,222 ऑप्स / सेकंड) है, जबकि "लूप, कैश्ड वैल्यू, इनबिल्ड कोड" ने केवल 76,635 ऑप्स / सेकेंडरी / सेकंड / सेकंड / 38 सेकंड में बनाए। )
Fr0sT

@ Fr0sT आपका बेंचमार्क एक अलग परिदृश्य है, जो अनुक्रमणिका 1 से <= लंबाई तक सरणियों का अनुरेखण करता है। बेशक यह विभिन्न परिणामों के लिए नेतृत्व करने जा रहा है। यदि आप <लंबाई के साथ शून्य-आधारित सरणियों का पता लगाने की कोशिश करते हैं - जो मुझे लगता है कि यह सामान्य परिदृश्य है - आप पाएंगे कि परिणाम "लूप" के लिए एक सामान्य "के साथ बेहतर अनुकूलित किए गए हैं (कैश्ड लंबाई थोड़ी तेज़ होने के साथ)।
CGodo

Kyopaxa ने बेंचमार्क को बदल दिया (0 <= i <लंबाई), परिणाम समान हैं। "रिवर्स लूप, निहित तुलना, फंक्शन कॉल" ने 365 kops / sec स्कोर किया, जबकि "लूप, कैशेड वैल्यू, इनबिल्ट कोड" ने 350 kops / sec (FF 51)
Fr0sT

@ Fr0sT यदि आप शून्य-आधारित कैश-फॉर-लूप को बिना किसी समान तुलना के बदलते हैं, जैसे कि for(let i=0, j=array.length; i < j; i++), लूप के लिए फॉरवर्ड की गति काफी बढ़ जाती है। कुछ परीक्षणों पर मैंने इसे जीता, ज्यादातर यह त्रुटि के मार्जिन या रिवर्स लूप के भीतर था।
इसहाक बी

1
@IsaacB और सभी, खेद है कि मैंने नोटिस नहीं किया है कि बेंच काफी गलत है - सभी प्रत्यक्ष लूप्स iterate 1..length जबकि रिवर्स लूप्स iterate length..0 (गिरफ्तार [लंबाई] आइटम अमान्य है)। मैंने परीक्षण निर्धारित किए और अब वे निम्नलिखित परिणाम दिखाते हैं: "लूप, इनलाइन कोड" 360,616 ऑप्स / सेकंड "0.27%," लूप, कैशेड वैल्यू, इनबिल्ट कोड "345,786 ऑप्स / सेकंड ± 2.45% (सिस्को!)" रिवर्स लूप, निहित तुलना, इनलाइन कोड "322,640 ऑप्स / सेकंड% 2.90% (!!!)। FF51 द्वारा टेस्ट निष्पादित किए गए। नया बेंच यहाँ है jsbench.github.io/#6bdfcd262692ba80c16a68c88554281570 । तो ऐसा लगता है कि यह छोरों को कुरूप करने में कोई मतलब नहीं है।
Fr0sT

31

यदि आदेश महत्वपूर्ण नहीं है, तो मुझे यह शैली पसंद है:

for(var i = array.length; i--; )

यह लंबाई को कैश करता है और लिखने के लिए बहुत छोटा है। लेकिन यह उल्टे क्रम में सरणी पर पुनरावृति करेगा।


6
आपने इसे मार दिया।
विग्नेश राजा

क्या आपको i> = 0 की आवश्यकता नहीं है?
मारवाअहमद

3
@MarwaAhmad: नहीं, i--एक नंबर देता है और एक बार नंबर होने 0की falseवजह से होता है Boolean(0) === false
फेलिक्स क्लिंग

31

यह सिर्फ 2018 है इसलिए एक अपडेट अच्छा हो सकता है ...

और मुझे वास्तव में स्वीकृत जवाब से असहमत होना होगा । यह अलग-अलग ब्राउज़रों पर निर्भर करता है। कुछ forEachतेजी से करते हैं , कुछ for-loop, और कुछ while यहाँ सभी विधि http://jsben.ch/mW36e पर एक बेंचमार्क है

arr.forEach( a => {
  // ...
}

और जब से आप के लिए लूप की तरह देख सकते हैं, for(a = 0; ... )तो यह उल्लेख के लायक है कि 'बिना' वेरिएबल को विश्व स्तर पर परिभाषित किया जाएगा और यह नाटकीय रूप से गति को प्रभावित कर सकता है, इसलिए यह धीमा हो जाएगा।

डफ का उपकरण ओपेरा में तेजी से चलता है, लेकिन फ़ायरफ़ॉक्स में नहीं

var arr = arr = new Array(11111111).fill(255);
var benches =     
[ [ "empty", () => {
  for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
  for(var a = 0, l = arr.length; a < l; ++a)
    var b = arr[a] + 1;
}]
, ["for-loop++", () => {
  for(var a = 0, l = arr.length; a < l; a++)
    var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
  for(var a = 0; a < arr.length; ++a )
    var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
  for(var a = arr.length - 1; a >= 0; --a )
    var b = arr[a] + 1;
}]
,["while-loop", () => {
  var a = 0, l = arr.length;
  while( a < l ) {
    var b = arr[a] + 1;
    ++a;
  }
}]
, ["reverse-do-while-loop", () => {
  var a = arr.length - 1; // CAREFUL
  do {
    var b = arr[a] + 1;
  } while(a--);   
}]
, ["forEach", () => {
  arr.forEach( a => {
    var b = a + 1;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
  // Here if you forget to put 'var' so variables'll be global
  for(a = 0, l = arr.length; a < l; ++a)
     var b = arr[a] + 1;
});
var times = benches.map( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [a[0], bench(...a)]
                     }).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div {  clear:both   }
body > div > div > span {
  float:left;
  width:43%;
  margin:3px 0;
  text-align:right;
}
body > div > div > span:nth-child(2) {
  text-align:left;
  background:darkorange;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>


3
@Maykonn आप शायद कहना चाहते थे "और यह हर जगह काम करता है लेकिन ओपेरा मिनी"
dube

3
@Maykonn जो डिफ़ॉल्ट दृश्य में सूचीबद्ध नहीं है, क्योंकि सभी उपयोगकर्ताओं के 0.18% में IE8 है और आपको इसका समर्थन करने की कोशिश में समय बर्बाद नहीं करना चाहिए; 2018 में यह एक मृत घोड़ा है।
dube

1
यह निश्चित रूप से सच है यदि आप दुनिया भर के सभी उपयोगकर्ताओं पर विचार करते हैं। लेकिन, दुर्भाग्य से, दुनिया के विशिष्ट भागों में IE8 अभी तक प्रासंगिक है।
मेकॉन्ग

1
यदि मैं कर सकता हूं, तो न केवल अलग-अलग ब्राउज़रों के अलग-अलग तरीकों के साथ अलग-अलग परिणाम होंगे, बल्कि एक ही ब्राउज़र के अलग-अलग इनपुट के साथ अलग-अलग परिणाम होंगे। एक विशाल संख्या केवल ऐरे को बहुत अनुकूलित किया जाएगा, जबकि एक छोटा मिश्रित एक नहीं होगा।
काइदो

1
@ ताहिल धन्यवाद
nullqube

19

2014 Whileवापस आ गया है

बस तार्किक सोचो।

इसे देखो

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. कम से कम 2 चर (इंडेक्स, लंबाई) बनाने की आवश्यकता
  2. यह जाँचने की आवश्यकता है कि क्या सूचकांक लंबाई से छोटा है
  3. सूचकांक बढ़ाने की जरूरत है
  4. forपाश 3 पैरामीटर

अब मुझे बताइए कि इससे अधिक तेज़ क्यों होना चाहिए:

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. एक चर
  2. कोई जांच नहीं
  3. सूचकांक कम हो गया है (मशीनें पसंद करती हैं)
  4. while केवल एक पैरामीटर है

मैं पूरी तरह से भ्रमित था जब क्रोम 28 ने दिखाया कि लूप थोड़ी देर के लिए तेज है। यह किसी प्रकार का होना चाहिए

"उह, हर कोई लूप के लिए उपयोग कर रहा है, चलो उस पर ध्यान केंद्रित करें जब क्रोम के लिए विकसित हो।"

लेकिन अब, 2014 में जबकि लूप क्रोम पर वापस आ गया है। यह 2 गुना तेज है, अन्य / पुराने ब्राउज़रों पर यह हमेशा तेज था।

हाल ही में मैंने कुछ नए परीक्षण किए। अब वास्तविक दुनिया में उन छोटे कोडों की कीमत कुछ भी नहीं है और jsperf वास्तव में लूप को ठीक से निष्पादित नहीं कर सकते, क्योंकि इसमें array.length को फिर से बनाने की जरूरत होती है जिसमें समय भी लगता है।

आप jsperf पर थोड़ी देर के लूप की वास्तविक गति प्राप्त नहीं कर सकते।

आपको अपना स्वयं का कस्टम फ़ंक्शन बनाने और उसके साथ जांच करने की आवश्यकता है window.performance.now()

और हाँ ... कोई उपाय नहीं है जबकि लूप बस तेज है।

वास्तविक समस्या वास्तव में डोम हेरफेर / प्रतिपादन समय / ड्राइंग समय है या फिर भी आप इसे कॉल करना चाहते हैं।

उदाहरण के लिए मेरे पास एक कैनवास दृश्य है जहां मुझे निर्देशांक और टकरावों की गणना करने की आवश्यकता है ... यह 10-200 माइक्रोसेकंड (मिलीसेकंड नहीं) के बीच किया जाता है। यह वास्तव में सब कुछ प्रदान करने के लिए विभिन्न मिलीसेकंड लेता है। जैसा कि डोम में है।

परंतु

loopकुछ मामलों में उपयोग करने के लिए एक और सुपर परफ़ॉर्मर तरीका है ... उदाहरण के लिए किसी सरणी को कॉपी / क्लोन करने के लिए

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

मापदंडों के सेटअप पर ध्यान दें:

  1. उसी समय में जैसे कि मैं केवल एक चर का उपयोग कर रहा हूं
  2. यह जांचने की आवश्यकता है कि क्या सूचकांक 0 से बड़ा है;
  3. जैसा कि आप देख सकते हैं कि यह लूप हर किसी के उपयोग के लिए सामान्य बनाम अलग है, जैसा कि मैं 3 वें पैरामीटर के अंदर सामान करता हूं और मैं सीधे सरणी के अंदर भी घटता हूं।

कहा कि, यह पुष्टि करता है कि मशीनों की तरह -

यह लिखना कि मैं इसे थोड़ा छोटा बनाने और कुछ बेकार सामान निकालने के बारे में सोच रहा था और यह लिखा कि इसी शैली का उपयोग करके:

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

यहां तक ​​कि अगर यह छोटा है तो ऐसा लगता है कि iएक बार और उपयोग करने से सब कुछ धीमा हो जाता है। यह पिछले forलूप और whileएक की तुलना में 1/5 धीमा है ।

नोट:; बिना looo के लिए के बाद बहुत महत्वपूर्ण है{}

यहां तक ​​कि अगर मैंने अभी आपको बताया है कि स्क्रिप्ट्स का परीक्षण करने के लिए jsperf सबसे अच्छा तरीका नहीं है .. तो मैंने इस 2 छोरों को यहां जोड़ा

http://jsperf.com/caching-array-length/40

और यहां जावास्क्रिप्ट में प्रदर्शन के बारे में एक और जवाब है

https://stackoverflow.com/a/21353032/2450730

यह उत्तर जावास्क्रिप्ट लिखने के प्रदर्शन के तरीके को दिखाना है। इसलिए यदि आप पढ़ नहीं सकते हैं, तो पूछें और आपको एक उत्तर मिलेगा या जावास्क्रिप्ट http://www.ecma-international.org/ecma-262/5.1/ के बारे में एक पुस्तक पढ़ें


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

समझाएं, इसलिए शायद मैं उत्तर को सही कर सकता हूं या कुछ नया सीख सकता हूं। btw जवाब अब एक वर्ष से अधिक पुराना है ... ब्राउज़र समय के साथ बदल सकते हैं जैसा कि वे हमेशा करते हैं ...
cocco

मेरी राय में, जबकि (--length) बुराई है क्योंकि यह तकनीकी रूप से काम करता है क्योंकि 0 गलत है, 0 है और गलत वास्तव में एक ही शब्द शब्दार्थ नहीं है।
scott.korin

हाँ ... यह अब एक पुरानी पोस्ट है ... लेकिन हाँ, जबकि मुझे सादगी पसंद है। और निश्चित रूप से जैसा कि आप दोनों मामलों में इसका उल्लेख करते हैं, आपको यह जानना होगा कि क्या लिखना है। दूसरी तरफ मुझे कभी भी नकारात्मक संख्याओं को कम करने की आवश्यकता नहीं थी।
कोको

9
"मशीनें इसे पसंद करती हैं" एक कपड़े धोने के डिटर्जेंट के लिए एक विज्ञापन से एक वाक्य की तरह लगता है
कोको बीन

11

http://jsperf.com/caching-array-length/60

परीक्षण का नवीनतम संशोधन, जो मैंने तैयार किया (पुराने का पुन: उपयोग करके), एक बात दिखाता है।

कैशिंग की लंबाई इतनी महत्वपूर्ण नहीं है, लेकिन यह नुकसान नहीं पहुंचाती है।

मेरे डेबियन स्क्वीज़ 64-बिट ( मेरे डेस्कटॉप हार्डवेयर ) में क्रोम, ओपेरा और फ़ायरफ़ॉक्स में पिछले 4 स्निपेट्स (चार्ट में अंतिम 4, 5 वें, 7 वें और 10 वें स्थान पर) के लिए ऊपर दिए गए परीक्षण के हर पहले रन (ताज़ा खुले टैब पर) सर्वश्रेष्ठ परिणाम देता है। )। बाद के रन काफी अलग परिणाम देते हैं।

प्रदर्शन-वार निष्कर्ष सरल हैं:

  • लूप (फॉरवर्ड) के साथ जाएं और !==इसके बजाय परीक्षण का उपयोग करें <
  • यदि आपको बाद में सरणी का पुन: उपयोग करने की आवश्यकता नहीं है, तो जबकि विलंबित लंबाई और विनाशकारी- shift()सरणी पर लूप भी कुशल है।

tl; डॉ

आजकल (2011.10) नीचे पैटर्न सबसे तेज दिखता है।

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

यह ध्यान रखें कि यहां कैशिंग arr.lengthमहत्वपूर्ण नहीं है, इसलिए आप केवल परीक्षण कर सकते हैं i !== arr.lengthऔर प्रदर्शन नहीं छोड़ेंगे, लेकिन आपको छोटा कोड मिलेगा।


पुनश्च: मुझे पता है कि shift()इसके परिणाम के साथ स्निपेट में 0 वें तत्व तक पहुंचने के बजाय इसका उपयोग किया जा सकता है, लेकिन मैंने किसी तरह अनदेखी की कि पिछले संशोधन (जो कि लूप्स में गलत था) के पुन: उपयोग के बाद, और बाद में मैं पहले से ही प्राप्त परिणामों को खोना नहीं चाहता था।


वैरिएबल इंसर्ट बनाने से लूप जैसे करंट = अरेस्ट [i] एक परफॉर्मेंस (बड़ा मेमोरी एलोकेशन) कम हो सकता है? या लूप से पहले करंट घोषित करना बेहतर होगा? या लूप के अंदर सभी जगहों पर गिरफ्तारी [i] का उपयोग करें?
मकरोव सर्गेई

8

"शुद्ध प्रदर्शन में सर्वश्रेष्ठ?" या प्रदर्शन और पठनीयता?

शुद्ध प्रदर्शन "सर्वश्रेष्ठ" यह है, जो कैश का उपयोग करता है और ++ उपसर्ग ऑपरेटर (मेरा डेटा: http://jsperf.com/caching-array-length/189 )

for (var i = 0, len = myArray.length; i < len; ++i) {
  // blah blah
}

मैं तर्क दूंगा कि कैश-फॉर-लूप निष्पादन समय और प्रोग्रामर रीडिंग टाइम में सबसे अच्छा संतुलन है। हर प्रोग्रामर जो C / C ++ / Java से शुरू होता है, वह इस एक के माध्यम से पढ़ने के लिए ms को बर्बाद नहीं करेगा

for(var i=0; i < arr.length; i++){
  // blah blah
}

2
पठनीयता के लिए +1। कोई फर्क नहीं पड़ता कि कितना अच्छा lenनाम है, किसी को हमेशा उस पहले लूप पर डबल लेना होगा। दूसरे लूप का इरादा स्पष्ट है।
जोश जॉन्सन

7

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

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**


6

यह अब तक का सबसे तेज़ तरीका है ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

इस बात को ध्यान में रखें कि यह एरे का उपभोग करेगा, इसे खाएगा, और कुछ भी नहीं छोड़ा जाएगा ...


2
arr.shift();इसके बजाय arr.pop() एरे रिवर्स को टाला जा सकता है।
चिंटू सी राजू

1
@Gargaroz यदि आपको एक जाब्स सर्विस से एक JSON मिल रहा है उदाहरण के लिए एक उत्पाद सूची पर एक चैट सेवा या आइटम। एक और स्थिति जब आपको केवल एक बार सरणी का उपयोग करने की आवश्यकता होती है, उदाहरण के लिए एक चार्ट हो सकता है जो इंटरवल के आधार पर कई निर्देशांक प्राप्त करता है। कई उदाहरण हैं।
सर्जियो

कूल, आपको स्पष्टीकरण के लिए धन्यवाद, बहुत तरह का; क्या आप मुझे उस दिशा में इंगित कर सकते हैं जहाँ मुझे इस तरह के पाश का दोहन करने के लिए और उदाहरण मिल सकते हैं?
गागरोज

1
वर्तमान में Chrome 53 और फ़ायरफ़ॉक्स 48 में यह सबसे धीमे दृष्टिकोण में से एक है - perfjs.info/array-iteration
Pencroff

1
@ एलेरिज़ा सहमत हैं, मेरे जवाब में मेरे लिए भी एक टिप्पणी है।
सर्जियो

4

साल 2017 है

मैंने कुछ परीक्षण किए।

https://jsperf.com/fastest-way-to-iterate-through-an-array/

की तरह लग रहा है while विधि Chrome पर सबसे तेज़ है।

बाईं घटती तरह लग रहा है ( --i) ज्यादा दूसरों की तुलना में तेजी से होता है ( ++i, i--,i++ ) Firefox पर।

यह दृष्टिकोण औसतन उपवास है। लेकिन यह उल्टे क्रम में सरणी को पुनरावृत्त करता है।

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

यदि आगे का आदेश महत्वपूर्ण है, तो इस दृष्टिकोण का उपयोग करें।

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}

3
कीवर्ड का उपयोग करके letआप वास्तव में लूप प्रदर्शन के बजाय गुंजाइश निर्माण प्रदर्शन की तुलना कर रहे हैं। let i = 0, ii = array.lengthअपने forछोरों का उपयोग करके forब्लॉक के अंदर उन चर के लिए एक नया स्कोप बनाया जाएगा । आपके whileउदाहरण whileब्लॉक के अंदर चर के लिए एक नया स्कोप नहीं बनाते हैं और इसीलिए वे तेज़ होते हैं। यदि आप लूप के लिए अपने varबजाय का उपयोग letकरते हैं, तो आप देखेंगे कि लूप के लिए 2017 में व्हिल के रूप में अभी भी कितनी तेज़ है, लेकिन अधिक पठनीय है।
CGodo

यहाँ मैं किस बारे में बात कर रहा हूँ का एक jsperf है: jsperf.com/javascript-loop-testing-let-vs-var
CGodo

यह केवल Chrome में एक समस्या है। अन्य ब्राउज़रों में varऔर letएक ही प्रदर्शन है - stackoverflow.com/a/32345435/1785975
SeregPie

दिलचस्प। वैसे भी, मुझे " whileChrome में तेज़ " होने का कथन सटीक नहीं लगता है । letक्रोम में उस कीवर्ड के प्रदर्शन के मुद्दों के कारण उपयोग करने पर ही यह होता है । यदि varअन्य ब्राउज़रों का उपयोग या उनके साथ, forऔर whileबहुत अधिक समान हैं, तो कभी-कभी forबेंचमार्क के आधार पर और भी तेज होता है, और यह अधिक कॉम्पैक्ट और पठनीय इम्हो है।
CGodo

2

मैं हमेशा पहली शैली में लिखता हूं।

भले ही एक कंपाइलर इसे सरणियों के लिए अनुकूलित करने के लिए पर्याप्त स्मार्ट है, लेकिन फिर भी यह स्मार्ट है अगर हम यहां DOMNodeList का उपयोग कर रहे हैं या गणना की गई लंबाई के साथ कुछ जटिल वस्तु?

मुझे पता है कि सरणियों के बारे में सवाल क्या है, लेकिन मुझे लगता है कि एक शैली में अपने सभी छोरों को लिखना एक अच्छा अभ्यास है।


1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++, i ,i और i-- से तेज है

इसके अलावा, आप आखिरी बार गिरफ्तारी कर रहे [i ++] को अंतिम बार सहेज सकते हैं, जिसे आपको एक्सेस करने की आवश्यकता है (लेकिन यह डीबग करना कठिन हो सकता है)।

आप इसे यहाँ (अन्य लूप परीक्षणों के साथ) देख सकते हैं: http://jsperf.com/for-vs-OREpop/5


1
वर्तमान में Chrome 53 में यह सच है, लेकिन फ़ायरफ़ॉक्स 48 की गति समान है - perfjs.info/array-iteration
Pencroff

thunderguy.com/semicolon/2002/08/13/… कहते हैं ++iतेज ...
IMTheNachoMan

1

सितंबर 2017 तक ये jsperf परीक्षण क्रोम 60 पर सबसे अधिक प्रदर्शन करने वाला निम्न पैटर्न दिखा रहे हैं:

function foo(x) {
 x;
};
arr.forEach(foo);

किसी को पुन: पेश करने में सक्षम है?


हाँ यह सबसे तेज़ प्रतीत होता है, हालाँकि IE11 में इसे चलाने का प्रयास करें और वे विकल्प सबसे धीमे हैं। और फ़ायरफ़ॉक्स 55.03 में 'पुरानी बस्टेड कैश्ड लेन' 12mil को मिल रही है, जो कि 3.3k क्रोम की तुलना में एक चौंका देने वाला प्रदर्शन है। सभी ब्राउज़रों में प्रदर्शन के अनुरूप होने के लिए आपको प्रत्येक ब्राउज़र के लिए सबसे तेज़ औसत लूप का उपयोग करना चाहिए।
प्लिपी

0

मैंने एक विशाल सरणी को पुनरावृत्त करने के कुछ अन्य तरीकों की कोशिश की है और पाया है कि सरणी की लंबाई को आधा करना और फिर एक ही लूप में दोनों हिस्सों को पुनरावृत्त करना तेज है। विशाल सरणियों को संसाधित करते समय इस प्रदर्शन अंतर को देखा जा सकता है ।

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

उपर्युक्त विधि के लिए लूप वी.एस. लूप के बीच कुछ प्रदर्शन तुलना (टाइमर का उपयोग करके)।

http://jsfiddle.net/tejzpr/bbLgzxgo/


0

एक और jsperf.com परीक्षण: http://jsperf.com/ward-reverse-vs-for-cached-length

जबकि लूप रिवर्स सबसे तेज लगता है। केवल समस्या यह है कि जबकि (--i) 0. पर रुक जाएगा तो मैं अपने लूप में सरणी [0] का उपयोग कैसे कर सकता हूं?


2
यदि आप करते हैं while (i--)तो सत्यता का iपरीक्षण क्षय करने के बजाय क्षय होने से पहले और फिर सत्यता का परीक्षण करने से पहले किया जाएगा।
जस्टिन फिशर


0

जबकि लूप लूप की तुलना में थोड़ा तेज है।

var len = arr.length;
while (len--) {
    // blah blah
}

इसके बजाय लूप का उपयोग करें



-1

सबसे सुरुचिपूर्ण समाधान जो मुझे पता है कि नक्शे का उपयोग कर रहा है।

var arr = [1,2,3];
arr.map(function(input){console.log(input);});

46
सवाल लूप के माध्यम से पुनरावृति के सबसे धीमे रास्ते के लिए नहीं पूछ रहा है
eoleary


-1

किसी सरणी में लूप का तेज़ तरीका फ़िल्टर का उपयोग करके है। फ़िल्टर () विधि सभी तत्वों के साथ एक नया सरणी बनाता है जो प्रदान किए गए फ़ंक्शन द्वारा कार्यान्वित परीक्षण को पास करता है।

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

अपने अनुभव से, मैं हमेशा फिल्टर, मानचित्र आदि को प्राथमिकता देता हूं।


सवाल यह है कि सरणी को एक नए सरणी में कॉपी नहीं करने के लिए कम से कम समय में सरणी पर पुनरावृत्ति करना।
राहुल कड़ुकर २ Rahul

-1

2019 के रूप में वेबवॉकर अधिक लोकप्रिय रहा है, बड़े डेटासेट के लिए, हम मल्टी-कोर प्रोसेसर का पूरी तरह से उपयोग करके बहुत तेजी से संसाधित करने के लिए वेबवर्क का उपयोग कर सकते हैं।

हमारे पास Parallel.js भी हैं जो WebWorker को डेटा प्रोसेसिंग के लिए उपयोग करना बहुत आसान बनाते हैं।

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