2009-06-03 8 views
18

समस्या: मेरे पास एक विधि है जो जावा बाइटकोड के 8000 बाइट से अधिक संकलित है। हॉटस्पॉट में एक जादू सीमा है जो जेआईटी को 8000 बाइट्स से अधिक विधियों के लिए लात नहीं देती है। (हां, यह एक बड़ी विधि है। यह एक टोकननाइज़र लूप है।) विधि लाइब्रेरी में है और मैं पुस्तकालय के उपयोगकर्ताओं को जादू सीमा को निष्क्रिय करने के लिए हॉटस्पॉट को कॉन्फ़िगर करने की आवश्यकता नहीं चाहता हूं।क्या कोई जावा बाइटकोड अनुकूलक है जो बेकार गेटोस को हटा देता है?

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

प्रश्न: क्या जावा 5 क्लास फाइलों के लिए बाइटकोड ऑप्टिमाइज़र है जो पॉइंटलेस जंप चेन को फ़्लैट करता है और फिर अनावश्यक गेटोस को हटा देता है?

संपादित करें:

8698: goto 8548 
8701: goto 0 

जाहिर है, दूसरा गोटो केवल 8701 के लिए एक कूद के रूप में अच्छी तरह से एक दूसरे पर 0.

के लिए एक सीधा कूद हो सकता है जिसके द्वारा पहुंचा जा सकता है: मैं की तरह पैटर्न मतलब जांच, इस संदिग्ध पैटर्न ज्यादा आम है:

4257: if_icmpne 4263 
4260: goto 8704 
4263: aload_0 

कहाँ जाहिर है, एक, संकलक "इसके बराबर नहीं" तुलना करने के लिए "बराबर" तुलना उल्टा करने के लिए चाहते हैं 870 के लिए कूद 4 और गोटो को खत्म करो।

+3

कुछ आर्किटेक्चरों की एक सीमा है कि एक सापेक्ष शाखा कितनी दूर जा सकती है (क्योंकि वे 8 या 16 बिट रजिस्टर में पता रखते हैं) ताकि वे अक्सर एक रिश्तेदार शाखा के साथ एक गैर-रिश्तेदार शाखा के पास हो जाएं जो पूर्ण रूप से उपयोग किया जाता है कार्यक्रम काउंटर आकार। क्या ऐसा JVM है? –

+0

क्या आपका मतलब है * लेबल * केवल कूद से पहुंचने योग्य? –

+0

JVM को संकेत देने के लिए एक रनटाइम एनोटेशन निश्चित रूप से इस मामले में अच्छा लगेगा .... लेकिन मुझे नहीं लगता कि ऐसी चीज मौजूद है (और एक त्वरित Google कुछ भी नहीं बदलता है।) – Jared

उत्तर

0

8000 बाइट्स से अधिक संकलित एक विधि? क्या कोई उस कोड को समझता है? टेस्टेबल है? ऑप्टिमाइज़र के साथ परेशान होने के बजाय अर्थपूर्ण नामों के साथ इसे एकाधिक (निजी?) विधियों में विभाजित करने का प्रयास करें!

ठीक है, शायद मामले वैध बड़े तरीके हैं। लेकिन खेद है, सवाल में कोई संकेत नहीं हैं।

+1

लगता है कि वह एक पार्सर लिख रहा है - यह वास्तव में टोकननाइज़र लूप के लिए बहुत बड़ा है, और यह वास्तव में * इसे * रखने के लिए अधिक * पठनीय है। (मैंने लोगों को इस तरह की एक विधि को तोड़ने के लिए मजबूर किया है क्योंकि यह एन लाइनों से अधिक था और अगले महीने उन्होंने शिकायत की क्योंकि इसे पालन करना मुश्किल था ...) –

+2

हाँ, मैं कोड समझता हूं। यह रिकर्सिव वंश विधियों के रूप में किसी भी सुधार की तुलना में spec के लिए अधिक बारीकी से नक्शा बनाता है। हां, यह यूनिट परीक्षणों के एक बड़े सेट के साथ टेस्टेबल है। – hsivonen

1

मुझे आपका दर्द महसूस होता है। मुझे एक बार एक पार्सर लिखना पड़ा था जिसमें लगभग 5kloc था (str.equals (...)) कोड। मैंने parse1, parse2, आदि के आधार पर कई विधियों को तोड़ दिया। यदि parse1 का विश्लेषण नहीं किया गया है, तो पार्स 2 कहा जाता है, आदि यह आवश्यक रूप से सर्वोत्तम प्रथाओं के लिए नहीं है, लेकिन यह वही करता है जो आपको चाहिए ।

+1

बीटीडब्ल्यू: यदि आपको पता नहीं होता है, तो आपने parse1, parse2 आदि दृष्टिकोण के साथ "जिम्मेदारी की श्रृंखला" पैटर्न लागू किया है (यह नहीं कि यह इस समस्या के लिए एक बुरी या अच्छी बात है, बस इसका उल्लेख करना चाहता था। ..) –

+0

मेरे पास एक लूप में एक विशाल स्विच के बजाय कई विधियां होती थीं। हालांकि, विशाल स्विच संरचना बेहतर ढंग से फिट बैठती है और जब जेआईटी किक करता है तो तेज़ होता है। – hsivonen

+0

ठीक है आप हमेशा एक छोटा स्विच() कर सकते हैं और डिफ़ॉल्ट केस एक छोटे से स्विच के साथ दूसरी विधि को कॉल करता है और तब तक जब तक आप सभी बड़े नहीं होते स्विच मामलों को कवर किया गया है। यह एक बड़ी स्विच टेबल के रूप में उतना अच्छा नहीं होगा, लेकिन यह काम करेगा। मेरे मामले में मैं स्विच का उपयोग नहीं कर सका क्योंकि यह स्ट्रिंग्स पर काम नहीं करता है। – KitsuneYMG

0

यदि आप डीबग प्रतीकों (यानी javac में ध्वज) के साथ संकलित नहीं करते हैं तो इससे कोई फर्क पड़ता है? यह विधि को जादू सीमा से नीचे ला सकता है।

+0

कम से कम ग्रहण जावा कंपाइलर में संकलित विधि में बाइटकोड की संख्या पर इसका कोई प्रभाव नहीं पड़ता है। (मुझे लगता है कि डीबग तालिका अलग है।) – hsivonen

0

क्या विधि को विधि में रीफैक्टर करना असंभव होगा? आधुनिक जेआईटी की इनलाइन वैसे भी कॉल करती है।

+2

यदि आपने पहले एक पार्सर हाथ से लिखा नहीं है, तो कभी-कभी स्कैनर (लेक्सर/टोकनेज़र) बड़ा हो सकता है, लेकिन जब आप इसे विभाजित करते हैं तो पठनीयता नीचे जा सकती है। बेशक मैंने उसका कोड नहीं देखा है, लेकिन मैं वहां गया हूं ... –

+0

मैंने पहले से ही वास्तविक टोकननाइज़र क्रियाओं को विभाजित कर दिया है जिन्हें नियंत्रण प्रवाह को प्रभावित किए बिना विभाजित किया जा सकता है। नियंत्रण संरचना स्वयं बहुत बड़ी है। – hsivonen

+1

@ स्कॉट, मैंने पहले एक पार्सर लिखा है। यदि यह बहुत जटिल है (किसी विशेष कारण के लिए) उपयुक्त पार्सर जनरेटर पर विचार करना उचित समय हो सकता है। –

0

यदि यह टोकननाइज़र लूप है, तो क्या यह मैपिंग के डेटा ड्रावेन सेट और उचित प्रतिबिंब के साथ ऐसा करना बेहतर होगा?

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

यह डेटा और कार्यान्वयन को सिंक में रखने का मुद्दा प्रस्तुत करता है, लेकिन आप अपने कोडबेस से डेटा को डॉकलेट या संभवतः एनोटेशन के साथ उत्पन्न कर सकते हैं।

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

+0

नहीं, आदर्श रूप से आप राज्य संक्रमण को कोड में कूदने के लिए संकलित करना चाहते हैं-डेटा संरचना लुकअप नहीं। – hsivonen

+0

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

0

यदि आप अपनी कक्षा में बाइटकोड सिकुड़ने वाला/obfuscator चलाते हैं तो आपके प्रदर्शन में वृद्धि होती है? उदाहरण के लिए, yguard, proguard, ...

शायद आप एएसएम का उपयोग कर एक क्लास फ़ाइल पोस्टप्रोसेसर लिख सकते हैं क्योंकि आपका उपयोग केस इतना विशिष्ट है।

भले ही आप सभी व्यर्थ गेटोस को हटा दें, क्या यह आपको जादू सीमा के तहत लाता है?

0

bytecode libraries की एक सूची BCEL और ASM का उल्लेख करती है, जिसे मैंने पहले सुना होगा, साथ ही कई अन्य चीजें कर रहे हैं।

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