प्रतिबिंब सामान्य से बहुत धीमी है

मैं वर्तमान में जावा प्रोजेक्ट पर काम कर रहा हूं जिसमें मैं इन्स और आउट सीखने की कोशिश कर रहा हूं। पिछली परियोजनाओं में, मैंने ऑब्जेक्ट में प्रत्येक गेटर को कॉल करके और मूल्य प्रदर्शित करने के लिए इसे पार्स करके एक toString() बनाने के लिए जावा प्रतिबिंब का उपयोग किया है। डेटा को प्रदर्शित करने के लिए यह विधि उपयोगी, स्वच्छ और गतिशील तरीका रही है।

नीचे मेरे कोड का एक बहुत ही सरल संस्करण है:

private static String objectToString(Object o) {
    LOGGER.debug("entering ObjectStringUtils::objectToString()");


    ....

    Class<?> oClass = o.getClass();
    String className = oClass.getName();
    Method[] methods = oClass.getMethods();

    for (Method m : methods) {
         if ([method is a getter]) {
               String methodName;
               Object value;
               try {
                   methodName= m.getName();
                   LOGGER.debug("Invoking " + className + "::" + methodName);
                   Object value = m.invoke(o);
                   LOGGER.debug("Invoked " + className + "::" + methodName);
               } catch (Exception e) {
                   e.printStackTrace();
                   value = null;
               }

               LOGGER.debug(methodName+ " -> " + value);
         }
    }
}

यह लॉगर आउटपुट उत्पन्न करता है जो इस तरह दिखता है:

14:47:49,478 [] DEBUG ObjectStringUtils:? - Invoking org.hibernate.impl.SessionImpl::isOpen
14:47:49,613 [] DEBUG ObjectStringUtils:? - Invoked org.hibernate.impl.SessionImpl::isOpen
14:47:49,613 [] DEBUG ObjectStringUtils:? - isOpen -> true

ध्यान दें कि फ़ंक्शन को कॉल करने के लिए जावा 13 9 मिलीसेकंड लिया गया था। किसी भी वर्ग में किसी भी विधि में प्रतिबिंब करने में यह लंबा समय लगता है, भले ही विधि केवल एक मानक गेटर है जो मूल्य वापस करने के अलावा कोई तर्क नहीं करता है। इसका मतलब है कि इसमें बहुत लंबा समय लगता है ऑपरेशन करने के लिए जब कई नेस्टेड मूल्य शामिल होते हैं। जब मैंने वेबस्पेयर 7 पर पहले प्रतिबिंब का उपयोग किया, तो ऑपरेशन करने के लिए इस लंबे समय तक इसका एक छोटा सा अंश लिया।

तो मेरा सवाल है: क्यों प्रक्रिया करने में इतना समय लग रहा है? मैं समझता हूं कि प्रतिबिंब धीमा है, लेकिन यह गेटटर को कॉल करने के लिए 140 मिलीसेकंड की परिमाण पर नहीं होना चाहिए। क्या यह वेबलॉगिक को फ़ंक्शन कॉल करने के लिए लंबे समय तक ले जाने का तरीका है, या तथ्य यह है कि रेखा संख्याओं को .class फ़ाइलों से अलग किया जाना प्रतीत होता है? अब तक, मुझे कोई विचार नहीं है।

0
@ जोशएम: किया, धन्यवाद।
जोड़ा लेखक patstuart, स्रोत
स्पष्टता के लिए आपको variableName को methodName का नाम बदलना चाहिए।
जोड़ा लेखक Josh M, स्रोत
क्या आपने इसे प्रोफाइल करने की कोशिश की है?
जोड़ा लेखक chrylis, स्रोत

2 उत्तर

जब आप कोड के एक टुकड़े को बेंचमार्क करते हैं, तो आपको एक ही ऑपरेशन कई बार करना होगा, अन्यथा परीक्षण व्यर्थ है - यह कचरा संग्रहण या उसी कंप्यूटर पर चल रही किसी अन्य प्रक्रिया के कारण हो सकता था।

0
जोड़ा
मैंने कोड के टुकड़े को कई सौ बार चलाया है, और इसमें कई मिनट लगते हैं। इसने कोड को कुछ सौ वर्गों में सक्रिय करते समय अनावश्यक होने का कारण बना दिया है।
जोड़ा लेखक patstuart, स्रोत

जब विधि s कैश किए जाते हैं - उदा। एक ढांचे में उपयोग किया जाता है और oClass.getMethods() केवल एक बार कहा जाता है, एक विधि के प्रति प्रतिबिंबित कॉल केवल एक विधि विधि कॉल से ~ 2-3 धीमी है। मुझे लगता है कि oClass.getMethods() आपके प्रतिबिंब में सबसे धीमा हिस्सा होना चाहिए, विधिवत आमंत्रण नहीं।

तो हो सकता है कि यह सत्र Impl :: isOpen हो जो स्वयं धीमा हो? अर्थात। यह जांचता है कि यह अभी भी जुड़ा हुआ है, या डेटाबेस के साथ कोई धीमी बातचीत है? डीबी लेनदेन के लिए भी 13 9 एमएस बहुत धीमी है, इसलिए यह भी इस कॉल के दौरान होने वाली कुछ त्रुटियों के कारण हो सकता है।

0
जोड़ा