2014-12-15 8 views
8

मैं नैशर्न का उपयोग करके कुछ प्रदर्शन-संवेदनशील कोड लागू कर रहा हूं। मैं इसे इस तरह कार्य करें:नैशर्न अक्षमता

private ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine(new String[] { "--no-java" }); 

String someExpression = "someFunction() + someVariable"; 

// this compiled script gets cached, caching code omitted 
CompiledScript script = ((Compilable)engine).compile(expr); 

MyScriptContext context = new MyScriptContext(); 

Object output = script.eval(context); 

रनटाइम पर, Nashorn MyScriptContext करने के लिए आवश्यक कॉल का एक बहुत बनाने पर जोर देता है। यह MyScriptContext.getBindings() को कॉल करने पर जोर देता है। प्रत्येक कॉल पर eval() nashorn.global ", anObject) डालें()। इसके बाद यह MyScriptContext.getAttribute ("कुछ उपलब्ध") (जिसे यह चाहिए) और MyScriptContext.getAttribute ("someFunction") पर कॉल करने के लिए एक कॉल करता है (जिसे यह नहीं करना चाहिए)।

इसे "कुछ फ़ंक्शन()" के लिए कॉल नहीं करना चाहिए क्योंकि यह फ़ंक्शन संकलन समय पर उपलब्ध था। "कुछ फ़ंक्शन()" को बाइटकोड में संकलित करने और संकलन समय पर बाध्य करने की आवश्यकता है, प्रत्येक कॉल पर eval() पर नहीं। eval() एक तंग पाश में है।

मैं नैशॉर्न को MyScriptContext पर कम कॉल करने के लिए कैसे राजी करूं?

+3

"मैं नैशर्न का उपयोग करके कुछ प्रदर्शन-संवेदनशील कोड को कार्यान्वित कर रहा हूं" आप एक स्क्रिप्टिंग भाषा में प्रदर्शन-संवेदनशील चीजों को क्यों लागू कर रहे हैं? – Holger

+4

क्योंकि मुझे करना है। यह एक बुनियादी आवेदन आवश्यकता है। और हाँ, यह इस आवेदन के संदर्भ में समझ में आता है। – ccleve

उत्तर

32

Nashorn के रूप में वैश्विक बाह्य नए सिरे से परिभाषित किया जा सकता है और वहाँ कोई रास्ता नहीं है पता करने के लिए वे नए सिरे से परिभाषित नहीं कर रहे हैं संदर्भ में हर विश्व स्तर पर परिभाषित चर (विश्व स्तर पर परिभाषित कार्यों सहित) को देखना होता है। इसलिए, हम कभी भी बाइटकोड में एक फ़ंक्शन को बाध्य नहीं कर सकते हैं। मैं प्रदर्शन में सुधार के लिए कई दृष्टिकोणों की रूपरेखा तैयार करूंगा।

एक तुरंत लागू गुमनाम समारोह अभिव्यक्ति में अपने कोड लपेटें

आपको गुमनाम समारोह के अंदर अपने कार्यक्रम को परिभाषित करने, इस प्रकार यह एक गैर वैश्विक विस्तार देकर प्रदर्शन में सुधार कर सकते हैं:

(function() { 
    // put your original code here, like this: 
    // ... 
    function someFunction() { ... } 
    ... 
    someFunction(); 
    ... 
})(); 

कि में केस, अज्ञात फ़ंक्शन के अंदर फ़ंक्शन ऑब्जेक्ट्स बाइटकोड स्थानीय चर में संग्रहीत किए जा सकते हैं। पैरामीटर के रूप में

सामान्य में

उन में पास करके वैश्विक पर निर्भरता कम करें, यदि आपका कोड प्रदर्शन प्रति संवेदनशील है, वैश्विक के अपने प्रयोग को कम। यदि आपको ग्लोबल्स का उपयोग करने की आवश्यकता है, तो आप उन्हें फ़ंक्शन के पैरामीटर में भी ले जा सकते हैं ताकि वे वहां स्थानीय चर बन जाए। जैसे यदि आपका कोड वैश्विक पर निर्भर करता है x और y, कार्य करें:

(function(x, y) { 
    // put your original code here, like this: 
    // ... 
    function someFunction() { ... } 
    ... 
    someFunction(); 
    ... 
})(x, y); 

जाहिर है, चर-पढ़ने के लिए उपयोग करने के लिए यह केवल काम करता है। (यह किसी भी फ़ंक्शन के साथ काम करता है, बेशक, केवल एक अज्ञात नहीं, तुरंत फ़ंक्शन अभिव्यक्ति का आह्वान करता है; यह केवल एक ऐसा निर्माण है जिसका उपयोग मैं करता हूं जब मुझे केवल वैश्विक शब्दावली संदर्भ से निजी में स्थानांतरित किया जाता है)।

उपयोग बाहरी गुमनाम समारोह कोड और मूल्यांकन

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

var program = (function() { 
    // put all your function declarations and other constants here 
    ... 
    function someFunction() { ... } 
    ... 
    return new function(x, y) { 
     // put your original code, minus the function declarations etc. here 
     ... 
     someFunction(); 
     ... 
    } 
})(); 

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

जावा से, अब आप script.eval() कर सकते हैं JSObject program = (JSObject)context.get("program") और इसके बाद program.call(null, x, y) के साथ इसे कई बार आमंत्रित करें। (JSObject देशी वस्तुओं के लिए नैशॉर्न का जावा-फेस इंटरफेस है, दोनों सामान्य और कार्य)।

वैकल्पिक रूप से, आप मंगलाचरण के लिए engine.compile("program(x, y)" का उपयोग कर एक अलग स्क्रिप्ट बना सकते हैं और यह ing eval() से पहले संदर्भ में x और y डाल करने के लिए सुनिश्चित करें।

आप इस तरह से दोहराए गए मूल्यांकन पर सबसे अधिक कटौती करेंगे। हालांकि ध्यान देना महत्वपूर्ण है कि सभी आमंत्रण बाहरी अज्ञात आमंत्रण के व्याख्यात्मक दायरे को साझा करेंगे। इस तरह आप उन्हें फिर से बनाने की ज़रूरत के बिना एक ही फ़ंक्शन ऑब्जेक्ट प्राप्त करते हैं, लेकिन यह भी सावधान रहें कि यदि आपके पास कोई म्यूटेबल स्थिति है (फ़ंक्शन स्कोप में कुछ var एस) तो उन्हें भी साझा किया जाएगा।

+2

यह एक उत्कृष्ट उत्तर है। आपको इसे कहीं भी एक ब्लॉग पोस्ट बनाना चाहिए। – ccleve

+0

@ccleve, आप दिए गए उत्तर पर टिप्पणी करते हैं और मैं आपसे सहमत हूं कि यह एक अच्छा जवाब है। लेकिन अधिक महत्वपूर्ण बात यह है कि आपने अपना सुझाव लागू किया है और यदि हां, तो क्या वे प्रदर्शन लाभ में भौतिक हैं? सुधार पर अपने प्रश्न टिप्पणी या अद्यतन करें। धन्यवाद! – Jeach

+0

क्या नैशोर्न के लिए कोई बेंचमार्क उपलब्ध है? हम वेबपैक द्वारा निर्मित जेएस बंडल चलाने की कोशिश कर रहे हैं और नैशर्न राइनो से धीमे लगते हैं (व्याख्या मोड में चल रहे हैं क्योंकि बंडल बहुत बड़ा है) 50% तक। क्या यह असली है, या हम कुछ याद कर रहे हैं? – Katona

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