javascript - V8 में इस कोड स्निपेट का उपयोग करके<= धीमा क्यों है?




(3)

अन्य उत्तरों और टिप्पणियों में उल्लेख किया गया है कि दो छोरों के बीच का अंतर यह है कि पहला एक दूसरे की तुलना में एक अधिक पुनरावृत्ति निष्पादित करता है। यह सच है, लेकिन एक सरणी में जो 25,000 तत्वों तक बढ़ती है, कम या ज्यादा एक पुनरावृत्ति केवल एक मामूली अंतर बना देगी। एक बॉलपार्क के अनुमान के अनुसार, अगर हम औसत लंबाई मान लेते हैं कि यह 12,500 है, तो हम जो अंतर की उम्मीद कर सकते हैं वह लगभग 1 / 12,500, या केवल 0.008% होना चाहिए।

यहां प्रदर्शन का अंतर उस एक अतिरिक्त पुनरावृत्ति द्वारा समझाया जाएगा, और प्रस्तुति के अंत में समस्या को समझाया गया है।

this.primes एक सन्निहित सरणी है (प्रत्येक तत्व एक मान रखता है) और तत्व सभी संख्याएँ हैं।

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

एक स्थिति यह होगी कि कुछ एरे तत्व गायब हैं। उदाहरण के लिए:

let array = [];
a[0] = 10;
a[2] = 20;

अब a[1] का मूल्य क्या है? इसका कोई मूल्य नहीं है । (यह कहना भी सही नहीं है कि इसका मान undefined - एक सरणी तत्व जिसमें undefined मान होता है, एक ऐसे सरणी तत्व से भिन्न होता है जो पूरी तरह से गायब है।)

केवल संख्याओं के साथ इसका प्रतिनिधित्व करने का कोई तरीका नहीं है, इसलिए जावास्क्रिप्ट इंजन को कम अनुकूलित प्रारूप का उपयोग करने के लिए मजबूर किया जाता है। यदि a[1] में अन्य दो तत्वों की तरह एक संख्यात्मक मान होता है, तो सरणी को केवल संख्याओं के एक सरणी में अनुकूलित किया जा सकता है।

यदि आप प्रस्तुति में चर्चा की गई सरणी के सीमा के बाहर किसी तत्व तक पहुंचने का प्रयास करते हैं, तो व्यूह-निर्मित प्रारूप में किसी सरणी के लिए मजबूर होने का दूसरा कारण हो सकता है।

पहले लूप के साथ <= सरणी के अंत में एक तत्व को पढ़ने का प्रयास करता है। एल्गोरिथ्म अभी भी सही ढंग से काम करता है, क्योंकि अंतिम अतिरिक्त पुनरावृत्ति में:

  • this.primes[i] undefined मूल्यांकन करता है क्योंकि i सरणी के अंत से अतीत i
  • candidate % undefined ( candidate % undefined के किसी भी मूल्य के लिए) NaN मूल्यांकन करता है।
  • NaN == 0 false मूल्यांकन करता false
  • इसलिए, return true निष्पादित नहीं किया गया है।

तो यह ऐसा है जैसे अतिरिक्त पुनरावृत्ति कभी नहीं हुई - इसका बाकी तर्क पर कोई प्रभाव नहीं है। कोड अतिरिक्त पुनरावृत्ति के बिना ही परिणाम उत्पन्न करता है।

लेकिन वहां पहुंचने के लिए, इसने सरणी के अंत में एक असंगत तत्व को पढ़ने की कोशिश की। यह सरणी को अनुकूलन से बाहर कर देता है - या कम से कम इस बात के समय।

< साथ दूसरा लूप केवल उन तत्वों को पढ़ता है जो सरणी के भीतर मौजूद हैं, इसलिए यह एक अनुकूलित सरणी और कोड की अनुमति देता है।

समस्या 90-91 के पन्नों में वर्णित है, उससे पहले और बाद के पृष्ठों में संबंधित चर्चा के साथ।

मैं इस Google I / O प्रस्तुति में शामिल हुआ और बाद में स्पीकर (V8 लेखकों में से एक) के साथ बात की। मैं अपने स्वयं के कोड में एक तकनीक का उपयोग कर रहा था जिसमें किसी विशेष परिस्थिति को अनुकूलित करने के प्रयास के रूप में एक सरणी के अंत में एक गुमराह (हिंद में) पढ़ने की कोशिश शामिल थी। उन्होंने पुष्टि की कि यदि आप किसी सरणी के अंत में भी पढ़ने की कोशिश करते हैं , तो यह सरल अनुकूलित प्रारूप का उपयोग करने से रोकेगा।

यदि V8 लेखक ने जो कहा वह अभी भी सत्य है, तो सरणी के अंत को पढ़ने से इसे अनुकूलित होने से रोका जा सकेगा और इसे धीमे स्वरूप में वापस आना होगा।

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

मैं वी 8 के साथ जावास्क्रिप्ट स्पीड लिमिट को तोड़ते हुए स्लाइड्स को पढ़ रहा हूं, और नीचे दिए गए कोड की तरह एक उदाहरण है। मैं यह पता नहीं लगा सकता कि <= इस मामले में धीमा है < , क्या कोई इसे समझा सकता है? किसी भी टिप्पणी की सराहना की है।

धीरे:

this.isPrimeDivisible = function(candidate) {
    for (var i = 1; i <= this.prime_count; ++i) {
        if (candidate % this.primes[i] == 0) return true;
    }
    return false;
} 

(संकेत: प्राइम लंबाई की एक सरणी है प्राइम_काउंट)

और तेज:

this.isPrimeDivisible = function(candidate) {
    for (var i = 1; i < this.prime_count; ++i) {
        if (candidate % this.primes[i] == 0) return true;
    }
    return false;
} 

[अधिक जानकारी] मेरे स्थानीय पर्यावरण परीक्षण में गति में सुधार महत्वपूर्ण है, परिणाम इस प्रकार हैं:

V8 version 7.3.0 (candidate) 

धीरे:

 time d8 prime.js
 287107
 12.71 user 
 0.05 system 
 0:12.84 elapsed 

और तेज:

time d8 prime.js
287107
1.82 user 
0.01 system 
0:01.84 elapsed

इसमें कुछ वैज्ञानिकता जोड़ने के लिए, यहाँ एक jsperf है

https://jsperf.com/ints-values-in-out-of-array-bounds

यह एक सरणी के नियंत्रण मामले का परीक्षण करता है जो कि इन्टस से भरा होता है और सीमा के भीतर रहकर मॉड्यूलर अंकगणित कर रहा होता है। इसके 5 परीक्षण मामले हैं:

  • 1. सीमा से बाहर लूपिंग
  • 2. होली सरण
  • 3. NaNs के खिलाफ मॉड्यूलर अंकगणित
  • 4. पूरी तरह से अपरिभाषित मूल्य
  • 5. एक new Array() का उपयोग करना new Array()

यह दर्शाता है कि प्रदर्शन के लिए पहले 4 मामले वास्तव में खराब हैं। सीमा से बाहर लूपिंग अन्य 3 की तुलना में थोड़ा बेहतर है, लेकिन सभी 4 सर्वश्रेष्ठ मामले की तुलना में लगभग 98% धीमी हैं।
new Array() मामला लगभग कच्चा सरणी जितना ही अच्छा है, बस कुछ प्रतिशत धीमा है।


TL; DR धीमा लूप एरे 'आउट-ऑफ-बाउंड्स' तक पहुँचने के कारण है, जो या तो इंजन को कम या कोई अनुकूलन के साथ फ़ंक्शन को फिर से शुरू करने के लिए मजबूर करता है या इसके साथ शुरू करने के लिए इनमें से किसी भी अनुकूलन के साथ फ़ंक्शन को संकलित नहीं करता है ( यदि (JIT-) कम्पाइलर ने पहले संकलन 'संस्करण' से पहले इस स्थिति का पता लगाया / संदेह किया, तो नीचे क्यों पढ़ें;

किसी को केवल यह कहना है (पूरी तरह से चकित किसी ने पहले से ही नहीं किया है):
एक समय हुआ करता था जब ओपी का स्निपेट एक प्रोग्रामिंग प्रोग्रामिंग बुक में एक वास्तविक उदाहरण होगा, जिसका उद्देश्य इस बात पर जोर देना था कि जावास्क्रिप्ट में 'सरणियों' को अनुक्रमित किया गया है जो 0 से शुरू हो रहा है, 1 नहीं, और इस तरह के उदाहरण के रूप में उपयोग किया जाता है। एक सामान्य 'शुरुआती गलती' (क्या आपको प्यार नहीं है कि मैं 'प्रोग्रामिंग एरर' वाक्यांश से कैसे बचता हूं ;) ): आउट-ऑफ-बाउंड्स ऐरे एक्सेस

उदाहरण 1:
0-आधारित इंडेक्सिंग (हमेशा ES262 में) का उपयोग करके 5 तत्वों के Dense Array (सन्निहित के बीच कोई अंतराल नहीं होता है) और वास्तव में प्रत्येक सूचकांक पर एक तत्व होता है।

var arr_five_char=['a', 'b', 'c', 'd', 'e']; // arr_five_char.length === 5
//  indexes are:    0 ,  1 ,  2 ,  3 ,  4    // there is NO index number 5



इस प्रकार हम वास्तव में < vs <= (या 'एक अतिरिक्त पुनरावृत्ति') के बीच प्रदर्शन अंतर के बारे में बात नहीं कर रहे हैं, लेकिन हम बात कर रहे हैं:
'सही स्निपेट (बी) गलत स्निपेट (ए) से ज्यादा तेज क्यों चलता है?'

इसका उत्तर 2-गुना है (हालांकि ES262 भाषा कार्यान्वयनकर्ता के दृष्टिकोण से दोनों अनुकूलन के रूप हैं):

  1. डेटा-प्रतिनिधित्व: मेमोरी में आंतरिक रूप से एरे को कैसे दर्शाया / संग्रहीत किया जाए (ऑब्जेक्ट, हैशमैप, 'वास्तविक' संख्यात्मक सरणी, आदि)
  2. फ़ंक्शनल मशीन-कोड: इन 'एरे' को एक्सेस / हैंडल (पढ़ने / संशोधित) करने वाले कोड को कैसे संकलित किया जाए

आइटम 1 पर्याप्त रूप से (और सही ढंग से IMHO) स्वीकृत उत्तर द्वारा समझाया गया है, लेकिन यह केवल आइटम 2 पर 2 शब्द ('कोड') खर्च करता है : संकलन

अधिक सटीक: JIT- संकलन और इससे भी महत्वपूर्ण बात JIT- RE -Compilation!

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

अब, जावास्क्रिप्ट कोड / पुस्तकालयों / उपयोग में वृद्धि के साथ, और याद रखना कि कितने संसाधन (समय / स्मृति / आदि) एक 'वास्तविक' संकलक का उपयोग करता है, यह स्पष्ट है कि हम वेब पेज पर आने वाले उपयोगकर्ताओं को लंबे समय तक इंतजार नहीं कर सकते (और उनकी आवश्यकता है) उपलब्ध है कि कई संसाधनों के लिए)।

निम्नलिखित सरल कार्य की कल्पना करें:

function sum(arr){
  var r=0, i=0;
  for(;i<arr.length;) r+=arr[i++];
  return r;
}

पूरी तरह से स्पष्ट है, है ना? किसी भी अतिरिक्त स्पष्टीकरण की आवश्यकता नहीं है, है ना? रिटर्न-प्रकार Number , है ना?
खैर .. नहीं, नहीं और नहीं ... यह इस बात पर निर्भर करता है कि आप नामांकित पैरामीटर पैरामीटर को किस तर्क से पास करते हैं ...

sum('abcde');   // String('0abcde')
sum([1,2,3]);   // Number(6)
sum([1,,3]);    // Number(NaN)
sum(['1',,3]);  // String('01undefined3')
sum([1,,'3']);  // String('NaN3')
sum([1,2,{valueOf:function(){return this.val}, val:6}]);  // Number(9)
var val=5; sum([1,2,{valueOf:function(){return val}}]);   // Number(8)

समस्या देखें? फिर विचार करें कि यह केवल बमुश्किल बड़े पैमाने पर संभावित क्रमांकन को स्क्रैप कर रहा है ... हम यह भी नहीं जानते हैं कि फ़ंक्शन RETURN को तब तक किस प्रकार का किया जाता है जब तक कि हम ...

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

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

JIT-Compilation (जस्ट इन टाइम के रूप में JIT) वर्तमान लोकप्रिय समाधान है।

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

इस सब में समय लगता है!

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

लंबी कहानी छोटी: सिर्फ इसलिए कि जावास्क्रिप्ट की भाषा के शब्दार्थों को अक्सर हमारी पीठ मिलती है (जैसे ओपी के उदाहरण में इस मूक बग के साथ) का मतलब यह नहीं है कि 'बेवकूफ' गलतियों से कंपाइलर के तेजी से मशीन-कोड को बाहर करने की संभावना बढ़ जाती है। यह मानता है कि हमने 'आमतौर पर' सही निर्देश लिखे हैं: वर्तमान मंत्र हम 'उपयोगकर्ताओं' (प्रोग्रामिंग भाषा का) होना चाहिए: संकलक की मदद करें, हम जो चाहते हैं उसका वर्णन करें, सामान्य मुहावरों का पक्ष लें (मूल समझ से asm.js पर संकेत लें) क्या ब्राउज़र अनुकूलन करने की कोशिश कर सकते हैं और क्यों)।

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

बिना किसी ऑब्जेक्ट गुण के पहुंच और सीमा सरणी तत्वों से बाहर एक अपवाद बढ़ाने के बजाय undefined मान लौटाता है। ये गतिशील विशेषताएं जावास्क्रिप्ट में प्रोग्रामिंग को सुविधाजनक बनाती हैं, लेकिन वे जावास्क्रिप्ट को कुशल मशीन कोड में संकलित करना भी मुश्किल बनाते हैं।

...

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

स्रोत:
"JITProf: पिन-पॉइंटिंग JIT-unfriendly JavaScript Code"
बर्कले प्रकाशन, 2014, लिआंग गोंग, माइकल प्रडेल, कौशिक सेन द्वारा।
http://software-lab.org/publications/jitprof_tr_aug3_2014.pdf

ASM.JS (बाउंड अरेंज एक्सेस को पसंद नहीं करता है):

आगे-समय संकलन

क्योंकि asm.js जावास्क्रिप्ट का एक सबसे बड़ा उपसमूह है, यह विनिर्देश केवल सत्यापन तर्क को परिभाषित करता है- निष्पादन शब्दार्थ केवल जावास्क्रिप्ट का है। हालांकि, मान्य asm.js आगे से (एओटी) संकलन के लिए उत्तरदायी है। इसके अलावा, AOT कंपाइलर द्वारा उत्पन्न कोड काफी कुशल हो सकता है, जिसमें विशेषता हो सकती है:

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

कोड जो मान्य करने में विफल रहता है, उसे पारंपरिक साधनों, जैसे, व्याख्या और / या सिर्फ-समय (JIT) संकलन द्वारा निष्पादन में वापस आना चाहिए।

http://asmjs.org/spec/latest/

और अंत में https://blogs.windows.com/msedgedev/2015/05/07/bringing-asm-js-to-chakra-microsoft-edge/
सीमा-जांच को हटाते समय इंजन के आंतरिक प्रदर्शन में सुधार के बारे में एक छोटी उपधारा थी (केवल लूप के बाहर सीमा-जांच को उठाते समय पहले से ही 40% का सुधार हुआ था)।



संपादित करें:
ध्यान दें कि कई स्रोत JIT-Recompilation के विभिन्न स्तरों के बारे में व्याख्या करने के लिए नीचे बात करते हैं।

ओपी के स्निपेट के बारे में उपरोक्त जानकारी के आधार पर सैद्धांतिक उदाहरण :

  • IsPrimeDiv अदृश्य को कॉल करें
  • संकलित सामान्य मान्यताओं का उपयोग करPPimeDiv अदृश्य है (जैसे सीमा से बाहर नहीं)
  • काम करो
  • BAM, अचानक सरणी सीमा से बाहर (दाईं ओर) पहुंचता है।
  • बकवास, इंजन का कहना है, चलो recompile है जो अलग-अलग (कम) मान्यताओं का उपयोग करते हुए PivimeDiv अदृश्य है, और यह उदाहरण इंजन यह पता लगाने की कोशिश नहीं करता है कि क्या यह वर्तमान आंशिक परिणाम का पुन: उपयोग कर सकता है, तो
  • धीमे फ़ंक्शन का उपयोग करके सभी काम को पुन: निष्पादित करें (उम्मीद है कि यह खत्म हो जाए, अन्यथा दोहराएं और इस बार कोड की व्याख्या करें)।
  • वापसी का परिणाम

इसलिए समय तब था:
पहला रन (अंत में विफल) + प्रत्येक पुनरावृत्ति आदि के लिए धीमी मशीन-कोड का उपयोग करके सभी काम फिर से कर रहा है .. इस सैद्धांतिक उदाहरण में स्पष्ट रूप से> 2 गुना अधिक समय लगता है !



EDIT 2: (अस्वीकरण: नीचे दिए गए तथ्यों में आधारित अनुमान)
जितना अधिक मैं इसके बारे में सोचता हूं, उतना ही मुझे लगता है कि यह उत्तर वास्तव में इस गलत दंड के लिए अधिक प्रभावी कारण बता सकता है कि गलत स्निपेट ए (या स्निपेट बी पर प्रदर्शन-बोनस, आप कैसे सोचते हैं) के आधार पर, ठीक है क्यों मैं इसे (स्निपेट ए) एक प्रोग्रामिंग त्रुटि कह रहा हूं:

यह बहुत आकर्षक है कि यह मान लिया जाए कि यह this.primes एक 'सघन व्यूह' है, जो या तो शुद्ध संख्यात्मक है

  • स्रोत-कोड में हार्ड-कोडेड शाब्दिक ('वास्तविक' सरणी बनने के लिए ज्ञात उत्कृष्ट उम्मीदवार के रूप में सब कुछ संकलन-समय से पहले ही संकलक के लिए जाना जाता है) या
  • आरोही क्रमिक क्रम में एक पूर्व-आकार ( new Array(/*size value*/) ) भरने वाले एक संख्यात्मक कार्य का उपयोग करके उत्पन्न होने वाली सबसे अधिक संभावना है (एक 'वास्तविक' सरणी बनने के लिए एक और लंबे समय से ज्ञात उम्मीदवार)।

हम यह भी जानते हैं कि primes ऐरे की लंबाई prime_count रूप में prime_count गई है ! (यह इरादे और निश्चित आकार का संकेत है)।

हम यह भी जानते हैं कि अधिकांश इंजन शुरू में Arrays को कॉपी-ऑन-संशोधित (जब ज़रूरत होती है) के रूप में पास करते हैं, जो उन्हें बहुत अधिक तेजी से नियंत्रित करता है (यदि आप उन्हें नहीं बदलते हैं)।

इसलिए यह मान लेना उचित है कि ऐरे primes सबसे पहले आंतरिक रूप से एक अनुकूलित ऐरे की संभावना है, जो निर्माण के बाद परिवर्तित नहीं होता है (कंपाइलर के लिए जानना आसान है अगर सृजन के बाद एरे कोडिफाई नहीं होता है) और इसलिए पहले से ही (यदि लागू हो तो) इंजन के लिए) एक अनुकूलित तरीके से संग्रहीत, बहुत ज्यादा के रूप में अगर यह एक Typed Array

जैसा कि मैंने अपने sum फ़ंक्शन उदाहरण के साथ स्पष्ट करने की कोशिश की है, जो तर्क (ओं) को पारित हो जाता है जो वास्तव में होने की जरूरत है और जैसे कि उस विशेष कोड को मशीन-कोड में कैसे संकलित किया जा रहा है। String को sum फ़ंक्शन में पास करना String को परिवर्तित नहीं करना चाहिए, लेकिन यह बदलना कि फ़ंक्शन JIT-Compiled कैसे है! पास करने के लिए एक ऐरे को पास करना मशीन-कोड के संस्करण के एक अलग (शायद इस प्रकार के लिए अतिरिक्त, या 'आकार' के रूप में वे इसे कहते हैं, जो पास हो गया)।

जैसा कि टाइप्ड_अरे की तरह के अपराधों को परिवर्तित करने के लिए थोड़ा बोनकस लगता है, कुछ-कुछ के लिए मक्खी पर क्लिक करें जबकि कंपाइलर जानता है कि यह फ़ंक्शन इसे संशोधित करने वाला भी नहीं है!

इन मान्यताओं के तहत जो 2 विकल्प छोड़ता है:

  1. नंबर-क्रंचर के रूप में संकलित करें, कोई आउट-ऑफ-बाउंड्स नहीं मानते हैं, अंत में आउट-ऑफ-बाउंड्स समस्या में चलते हैं, recompile और redo work (जैसा कि ऊपर 1 संपादित में सैद्धांतिक उदाहरण में उल्लिखित है)
  2. कंपाइलर पहले से ही पता चला है (या संदिग्ध?) बाउंड एसेस ऊपर-सामने और फ़ंक्शन जेआईटी-संकलित था जैसे कि तर्क पारित किया गया था एक धीमी वस्तु जिसके परिणामस्वरूप धीमी कार्यात्मक मशीन-कोड होता है (क्योंकि इसमें अधिक चेक / बातचीत / ज़बरदस्ती होगी। आदि।)। दूसरे शब्दों में: फ़ंक्शन को कुछ ऑप्टिमाइज़ेशन के लिए कभी भी योग्य नहीं किया गया था, इसे संकलित किया गया था जैसे कि यह एक 'विरल सरणी' (- जैसे) तर्क प्राप्त करता है।

मुझे अब वास्तव में आश्चर्य है कि इन 2 में से कौन सा है!





v8