मूल ईएस 6 वादे धीमे और ब्लूबर्ड से अधिक स्मृति-गहन क्यों हैं?


195

में इस बेंचमार्क , सूट Bluebird वादों की तुलना में ES6 वादे के साथ पूरा करने के लिए 4 बार समय लेता है, और भी बहुत स्मृति के रूप में 3.6 गुना उपयोग करता है।

C में लिखे गए v8 के मूल कार्यान्वयन की तुलना में एक जावास्क्रिप्ट पुस्तकालय इतना तेज़ और हल्का कैसे हो सकता है? ब्लूबर्ड वादों में मूल ईएस 6 वादों (प्लस अतिरिक्त उपयोगिता विधियों का एक गुच्छा) के समान एपीआई है।

क्या मूल कार्यान्वयन केवल बुरी तरह से लिखा गया है, या क्या इसका कोई दूसरा पहलू है जो मुझे याद आ रहा है?


ध्यान रखें कि आधुनिक जावास्क्रिप्ट कार्यान्वयन भारी अनुकूलित हैं, और जेआईटी का उपयोग करके मूल रूप से भी चला सकते हैं ।

1
इस बेंचमार्क के अनुसार , ब्लूबर्डज वास्तव में नेटिव प्रॉमिस की तुलना में धीमा है। लेकिन, PromiseMeSpeedJS वास्तव में उन दोनों को पीछे छोड़ देता है। PromiseMeSpeedJS के माध्यम से यह साबित होता है कि वादों के लिए एक प्रमुख प्रदर्शन अपराधी newऑपरेटर का अपमानजनक अति प्रयोग है क्योंकि PromiseMeSpeedJS उपयोग नहीं करता है new
जैक गिफिन

1
@JackGiffin Chrome 67: PromiseMeSpeedJS 46% धीमा है और ब्लूबर्ड 61% धीमा है।
फ़िनडार्कसाइड

जवाबों:


272

ब्लूबर्ड लेखक यहाँ।

V8 वादों के क्रियान्वयन को जावास्क्रिप्ट सी। में नहीं लिखा गया है । सभी जावास्क्रिप्ट (V8 के अपने सहित) को मूल कोड में संकलित किया गया है। मूल कोड से संकलित होने से पहले, इसके अतिरिक्त, लिखा हुआ जावास्क्रिप्ट, यदि संभव हो (और इसके लायक है), तो उपयोगकर्ता अनुकूलित है। वादे का क्रियान्वयन एक ऐसी चीज है जो सी में लिखे जाने से बहुत अधिक या बिल्कुल भी लाभान्वित नहीं होगा, वास्तव में यह केवल इसे धीमा कर देगा क्योंकि आप जो भी कर रहे हैं वह जावास्क्रिप्ट ऑब्जेक्ट और संचार में हेरफेर कर रहा है।

V8 कार्यान्वयन केवल ब्लूबर्ड के रूप में अनुकूलित नहीं है, यह उदाहरण के लिए वादों के हैंडलर के लिए सरणियों को आवंटित करता है । यह बहुत सारी मेमोरी लेता है, जब प्रत्येक वादे में कुछ सरणियों का आवंटन करना होता है (बेंचमार्क समग्र 80k वादे बनाता है ताकि 160k अप्रयुक्त सरणियों को आवंटित किया जाए)। वास्तव में 99.99% उपयोग के मामलों में कभी भी एक से अधिक बार वादा नहीं किया जाता है, इसलिए इस सामान्य मामले के लिए अनुकूलन करने से भारी स्मृति उपयोग में सुधार होता है।

यहां तक ​​कि अगर V8 ने ब्लूबर्ड के रूप में एक ही अनुकूलन लागू किया, तो यह अभी भी विनिर्देश द्वारा बाधित होगा। बेंचमार्क को new Promise(ब्लूबर्ड में एक विरोधी पैटर्न) का उपयोग करना पड़ता है क्योंकि ईएस 6 में रूट वादा बनाने का कोई अन्य तरीका नहीं है। new Promiseएक वादा बनाने का एक बहुत ही धीमा तरीका है, पहले निष्पादक फ़ंक्शन एक क्लोजर आवंटित करता है, दूसरा यह तर्क के साथ 2 अलग-अलग क्लोजर्स को पारित किया जाता है। यह 3 बंदे प्रति वादा आवंटित है लेकिन एक बंद पहले से ही एक अनुकूलित वादे की तुलना में अधिक महंगी वस्तु है।

ब्लूबर्ड उपयोग कर सकता है promisifyजो बहुत सारे अनुकूलन सक्षम करता है और कॉलबैक एपीआई का उपभोग करने का एक अधिक सुविधाजनक तरीका है और यह पूरे मॉड्यूल को एक लाइन ( promisifyAll(require('redis'));) में वादा आधारित मॉड्यूल में बदलने में सक्षम बनाता है ।


10
"अभी भी विनिर्देश द्वारा बाधा है" - निश्चित नहीं कि इसका क्या मतलब है। क्या आप कह रहे हैं कि ES6 एक युक्ति का अनुसरण कर रहा है जो स्वाभाविक रूप से धीमा है, और यदि ऐसा है, तो क्या इसका मतलब यह है कि ब्लूबर्ड एक ही युक्ति का अनुसरण नहीं कर रहा है (और यदि ऐसा है, तो क्या यह एक भिन्न का अनुसरण कर रहा है, और कौन सा)? और क्या कोई कारण है कि ईएस 6 के अलावा एक रूट प्रॉमिस बनाने का बेहतर तरीका नहीं हो सकता है new Promiseया इसे कम खर्चीला बनाने के लिए तात्कालिकता में सुधार कर सकता है (जैसे प्रति मिनट 3 क्लोजर नहीं बनाना)?
एंथनी

12
यह (जेएस के लिए) बिल्कुल भी अच्छा नहीं लगता। आंतरिक कार्यान्वयन होने पर मैं वास्तव में एक वादा पुस्तकालय का उपयोग नहीं करना चाहता। यह सभी के लिए दुर्भाग्यपूर्ण स्थिति से अधिक है अगर यह सब सच है। लेकिन मुझे पहले से ही प्रोमिस-हाईप को देखने में पहले से ही परेशानी है, मैंने 100,000 LoC JS ऐप्स लिखे हैं और मुझे अभी भी इसके लिए कोई वास्तविक आवश्यकता नहीं दिख रही है, यह बहुत मामूली सुधार है यदि मेरे लिए , ज्यादातर त्रुटि से निपटने में, नहीं कॉलबैक हैंडलिंग में सुधार (मैं अपनी कोडिंग शैली के साथ "कॉलबैक नरक" में कभी नहीं रहा)।
मोर

19
ES6 में, आप Promise.resolve()"मूल वादा" बनाने के लिए उपयोग नहीं कर सकते हैं ?
16

10
@ MörreNoseshine (जारी) वर्षों बाद, ES6 लेखक साथ आए और कहा "हे, चलो निर्दिष्ट करते हैं कि JS इंजन को एक सामान्य वादा / A + अनुरूपित उपयोगिता आउट-ऑफ-द-बॉक्स प्रदान करना होगा, इसलिए लोगों के पास हमेशा एक मूल वादा करने का उपकरण होता है। "। यह एक अच्छी सुविधा है (सिर्फ एक त्वरित Promise.resolve()या जो भी करने के लिए एक पुस्तकालय आयात करने के लिए नहीं ), लेकिन यह एक बहुत ही बुनियादी कार्यान्वयन है, और इसके अस्तित्व को आपको ब्लूबर्ड जैसे अधिक गंभीर वादे से संबंधित उपकरणों का उपयोग करने से नहीं रोकना चाहिए!
कॉलम

11
@ MörreNoseshine 100k LOC जावास्क्रिप्ट एप्लिकेशन है कि शायद किसी भी async कार्यक्षमता नहीं था। सौभाग्य एक 100k LoC जेएस खेल के साथ एक mysql / redis पुस्तकालय के बिना ब्लूबर्ड लिख रहा है।
NiCk न्यूमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.