क्या JVM टेल कॉल ऑप्टिमाइज़ेशन को रोकता है?


99

मैंने इस उद्धरण को इस प्रश्न पर देखा: एक अच्छी कार्यात्मक भाषा क्या है जिस पर वेब सेवा का निर्माण किया जाता है?

विशेष रूप से स्काला स्व-पुनरावर्ती कार्यों को छोड़कर पूंछ-कॉल उन्मूलन का समर्थन नहीं करता है, जो आपके द्वारा की जाने वाली रचना के प्रकार को सीमित करता है (यह जेवीएम की एक मौलिक सीमा है)।

क्या ये सच है? यदि हां, तो जेवीएम के बारे में ऐसा क्या है जो इस मौलिक सीमा को बनाता है?

जवाबों:


74

यह पोस्ट: पुनरावृत्ति या Iteration? मदद हो सकती है।

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

सन बग # 4726340 में भी अधिक चर्चा है , जहां मूल्यांकन (2002 से) समाप्त होता है:

मेरा मानना ​​है कि यह फिर भी किया जा सकता है, लेकिन यह कोई छोटा काम नहीं है।

वर्तमान में, दा विंची मशीन परियोजना में कुछ काम चल रहा है । टेल कॉल उपप्रोजेक्ट की स्थिति "प्रोटो 80%" के रूप में सूचीबद्ध है; इसे जावा 7 में बनाने की संभावना नहीं है, लेकिन मुझे लगता है कि जावा 8 में इसका बहुत अच्छा मौका है।


मैंने स्पष्टीकरण का काफी पालन नहीं किया। मुझे लगा कि कंपाइलर द्वारा टेल-कॉल ऑप्टिमाइज़ेशन लागू किया गया था। मान लें कि आपके पास एक फ़ंक्शन है जो संकलक द्वारा अनुकूलित टेल-कॉल हो सकता है, तो आप एक समान गैर-पुनरावर्ती फ़ंक्शन भी कर सकते हैं जो लूप का उपयोग करके समान कार्यक्षमता को लागू करता है, सही? यदि ऐसा है, तो यह संकलक द्वारा नहीं किया जा सकता है। मैं जेवीएम पर निर्भरता का पालन करने में सक्षम नहीं हूं। यह एक योजना संकलक के साथ तुलना कैसे करता है जो देशी i386 कोड उत्पन्न करता है?
गौतम गणपति

4
@ गौतम: डिबगिंग के बारे में मेरा बयान जेवीएम पर टेल कॉल उन्मूलन की कमी के लिए एक समाधान के रूप में ट्रैंपोलिन का उपयोग करने के संदर्भ में था। टेल कॉल एलिमिनेशन को JVM (OpenJDK, और LLVM में भी किया गया है) पर लागू किया गया है, इसलिए ऐसा कोई सवाल नहीं है कि क्या किया जा सकता है या नहीं। माइक्रोसॉफ्ट के सीएलआर ने, निश्चित रूप से, 10 साल के लिए समर्थित टेल कॉल उन्मूलन और एफ # की रिहाई ने दिखाया है कि यह गेम चेंजर है। मुझे लगता है कि जवाब है कि जेवीएम लंबे समय से स्थिर है।
JD

3
यह एक सामान्य गलत धारणा और एक बार-बार दोहराया जाने वाला बहाना है, लेकिन गलत है। यह कई वर्षों के लिए अच्छी तरह से स्थापित किया गया है कि स्टैक निरीक्षण द्वारा सुरक्षा (और उपयोगी स्टैक निशान का प्रावधान) उचित पूंछ कॉल के साथ असंगत नहीं है। उदाहरण के लिए, 2004 से इस पेपर को देखें। उत्तर गलत है, क्योंकि यह गलत है। citeseerx.ist.psu.edu/viewdoc/… डाउनवोटिंग।
जस्टिन शेही

5
@JustinSheehy: क्या गलत है? सवाल था, "क्या जेवीएम पूंछ कॉल अनुकूलन को रोकता है?" और जवाब है, "नहीं, लेकिन यह कठिन है।"
माइकल मायर्स

5
क्या आपको पता है कि java8 में यह शामिल है?
नचोक २४'१४

27

मौलिक सीमा केवल यह है कि JVM अपने बाइट कोड में टेल कॉल प्रदान नहीं करता है और, परिणामस्वरूप, JVM पर टेल कॉल प्रदान करने के लिए JVM पर निर्मित भाषा का कोई सीधा रास्ता नहीं है। ऐसे वर्कअराउंड हैं जो एक समान प्रभाव प्राप्त कर सकते हैं (उदाहरण के लिए trampolining) लेकिन वे भयानक प्रदर्शन की गंभीर लागत पर आते हैं और उत्पन्न मध्यवर्ती कोड को बाधित करते हैं जो एक डिबगर को बेकार बनाता है।

इसलिए JVM किसी भी उत्पादन-गुणवत्ता वाली कार्यात्मक प्रोग्रामिंग भाषाओं का समर्थन नहीं कर सकता, जब तक कि सूर्य JVM में टेल कॉल को लागू न कर दे। वे वर्षों से इस पर चर्चा कर रहे हैं, लेकिन मुझे संदेह है कि वे कभी भी टेल कॉल को लागू करेंगे: यह बहुत मुश्किल होगा क्योंकि उन्होंने इस तरह की बुनियादी कार्यक्षमता को लागू करने से पहले अपने वीएम को समय से पहले अनुकूलित किया है, और सूर्य का प्रयास कार्यात्मक भाषाओं के बजाय गतिशील भाषाओं पर दृढ़ता से केंद्रित है।

इसलिए एक बहुत मजबूत तर्क है कि स्काला एक वास्तविक कार्यात्मक प्रोग्रामिंग भाषा नहीं है: इन भाषाओं ने टेल कॉल को एक आवश्यक विशेषता माना है क्योंकि योजना को 30 साल पहले शुरू किया गया था।


5
Hence there is a very strong argument that Scala is not a real functional programming language - तर्क वास्तव में काफी कमजोर है। यकीन है tail calls [as] an essential feature, और अच्छा है अगर अंतर्निहित हार्डवेयर (या पुण्य मशीन) इसे सीधे समर्थन करता है। लेकिन यह कार्यान्वयन विवरण है।
इंगो

8
@Ingo: केवल तभी जब आप उपयोगकर्ता द्वारा एक महत्वपूर्ण समस्या के रूप में देखे गए रन-टाइम पर अपने कार्यक्रम में स्टैक ओवरफ्लो पर विचार नहीं करते हैं। इसके बग ट्रैकर के अनुसार, यहां तक ​​कि स्काला कंपाइलर भी स्टैक ओवरफ्लो से ग्रस्त हो गया है। यहां तक ​​कि सबसे अनुभवी स्काला डेवलपर्स अभी भी इसे गलत कर रहे हैं ...
जेडी

7
# का वकील होना ठीक है। लेकिन मैंने आपको लंबे समय तक (यहां तक ​​कि यूनेट में सालों पहले भी) हर उस चीज़ से दुश्मनी के लिए नोट किया है जो एफ # नहीं है, और फिर भी आपके विस्तार से पता चलता है कि आप नहीं जानते कि आप किस बारे में बात कर रहे हैं। यहाँ की तरह: आपका तर्क यह प्रतीत होता है कि एक भाषा जहाँ मैं एक प्रोग्राम लिख सकता हूँ जिसमें स्टैक ओवरफ़्लो के साथ गर्भपात करना कार्यात्मक नहीं है? लेकिन भाषाओं के लिए एक ही तर्क नहीं दिया जा सकता है कि मैं ढेर अतिप्रवाह को कैसे भड़का सकता हूं? इसलिए, पवित्र एफ # खुद को कार्यात्मक नहीं गिना जाएगा।
इंगो

7
@ इंगो: कार्यात्मक प्रोग्रामिंग में कई मुहावरों, जैसे पारस्परिक पुनरावृत्ति और निरंतरता गुजर शैली, काम करने के लिए टेल कॉल उन्मूलन की आवश्यकता हो सकती है। इसके बिना, आपके कार्यक्रम अतिप्रवाह को ढेर कर देंगे। यदि कोई भाषा मुहावरेदार कार्यात्मक कोड को मज़बूती से नहीं चला सकती है, तो क्या यह कार्यात्मक है? जवाब एक निर्णय कॉल है, जैसा कि आप कहते हैं, लेकिन व्यवहार में एक महत्वपूर्ण अंतर। मार्टिन ट्रोजर ने अभी इसके बारे में एक दिलचस्प ब्लॉग पोस्ट प्रकाशित की: martinsprogrammingblog.blogspot.com/2011/11/…
JD

2
अभी भी, सिर्फ इसलिए कि जेवीएम (अफसोस की बात है, कोई सवाल नहीं) टेल कॉल नहीं कर सकता इसका मतलब यह नहीं है कि टेल कॉल एलिमिनेशन असंभव है। यह ऐसा है जैसे कि एक ने कहा कि फ्लोटिंग पॉइंट गणना केवल FPUs वाले कंप्यूटर पर संभव है।
इंगो

22

Scala 2.7.x अंतिम तरीकों और स्थानीय कार्यों के स्व-पुनर्संयोजन (स्वयं को कॉल करने वाला) के लिए टेल-कॉल ऑप्टिमाइज़ेशन का समर्थन करता है।

स्कैला 2.8, ट्रम्पोलिन के लिए पुस्तकालय समर्थन के साथ भी आ सकता है, जो पारस्परिक रूप से पुनरावर्ती कार्यों को अनुकूलित करने की एक तकनीक है।

स्केला की स्थिति के बारे में जानकारी का एक अच्छा सौदा रिच डफ़र्टी के ब्लॉग में पाया जा सकता है ।


क्या आप, कृपया वर्तमान स्केला स्थिति पर प्रश्न अपडेट कर सकते हैं?
ओम-नॉम-नॉम

@ om-nom-nom AFAIK, कुछ भी नहीं बदला है, न तो स्काला की तरफ, न ही जेवीएम की तरफ।
डैनियल सी। सोबरल

8

लैम्ब्डा द अल्टीमेट (ऊपर पोस्ट किए गए लिंक मिमीर्स से) में जुड़े पेपर के अलावा, सन से जॉन रोज ने टेल कॉल ऑप्टिमाइज़ेशन के बारे में कुछ और कहा है।

http://blogs.oracle.com/jrose/entry/tail_calls_in_the_vm

मैंने सुना है कि यह किसी दिन JVM पर लागू हो सकता है। अन्य चीजों के बीच टेल कॉल सपोर्ट को दा विंची मशीन पर देखा जा रहा है।

http://openjdk.java.net/projects/mlvm/


0

सभी स्रोत जेवीएम को पूंछ पुनरावृत्ति के मामले में अनुकूलित करने में असमर्थ होने की ओर इशारा करते हैं, लेकिन जावा प्रदर्शन ट्यूनिंग पढ़ने पर (2003, ओवेरी) मैंने लेखक को यह दावा करते हुए पाया कि वह पूंछ पुनरावृत्ति को लागू करके अधिक पुनरावृत्ति प्रदर्शन प्राप्त कर सकता है।

आप पृष्ठ 212 पर उसका दावा पा सकते हैं ('पूंछ पुनरावृत्ति के लिए खोज' यह दूसरा परिणाम होना चाहिए)। क्या देता है?


आईबीएम ने अपने जेवीएम कार्यान्वयन (अनुकूलन के रूप में, इसलिए कोई गारंटी नहीं) में टीसीओ के कुछ रूप का समर्थन किया है। शायद जावा प्रदर्शन ट्यूनिंग के लेखकों ने सोचा कि यह सुविधा अंततः सभी जेवीएम द्वारा लागू की जाएगी। ibm.com/developerworks/java/library/j-diag8.html
llemieng
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.