दिलचस्प पोस्ट
ओरेकल पर AUTO_INCREMENT के साथ आईडी कैसे बनाऊँ? क्या फ़ायरबेज 3 में टोकन के सर्वर साइड सत्यापन करना अभी भी संभव है? जब MySQL के साथ STRAIGHT_JOIN का उपयोग करें क्या मैं SQL सर्वर से कुछ उपयोगकर्ताओं को प्रमाणित करने के लिए ADFS 2.0 का उपयोग कर सकता हूं? कोणीय जेएस आवेदन के लिए प्रक्षेपक में एनिमेशन को अक्षम कैसे करें क्रोम में जावास्क्रिप्ट के साथ कोई टैब केंद्रित है या नहीं, यह कैसे पता लगा सकता है? PHP में mysql_ * फ़ंक्शन का उपयोग क्यों नहीं किया जाना चाहिए? UIImageView जेस्चर (ज़ूम, घुमाने) प्रश्न फ्लेक्स कंटेनर में समान ऊंची पंक्तियां PHP में फ्लोट के आंशिक हिस्से को प्राप्त करने का सबसे अच्छा तरीका क्या है? जावास्क्रिप्ट: माउस व्हील ईवेंट को कैप्चर करें और पृष्ठ स्क्रॉल न करें? CollapsingToolbarLayout की शुरुआत ऊंचाई सेट करें पूर्ण विशेषाधिकार के साथ जावा फाइल को व्यवस्थापक के रूप में चलाएं आप कैसे यूनिट परीक्षण निजी विधियों कर सकते हैं? NSString के दाहिने अंत से व्हाइटस्पेस को कैसे निकालना है?

जावा प्रतिबिंब प्रदर्शन

किसी भी महत्वपूर्ण निष्पादन अंतर में क्लास कन्स्ट्रक्टर परिणाम को कॉल करने के बजाय प्रतिबिंब का उपयोग करते हुए एक ऑब्जेक्ट का निर्माण करना है?

Solutions Collecting From Web of "जावा प्रतिबिंब प्रदर्शन"

हाँ बिल्कुल। प्रतिबिंब के माध्यम से एक वर्ग को खोजना, परिमाण के द्वारा , अधिक महंगा है।

प्रतिबिंब पर जावा के प्रलेखन का हवाला देते हुए:

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

यहाँ एक साधारण परीक्षण है जो मैंने 5 मिनट में मेरी मशीन पर सन की गई, जो सन जेआरई 6u10 चल रहा है:

public class Main { public static void main(String[] args) throws Exception { doRegular(); doReflection(); } public static void doRegular() throws Exception { long start = System.currentTimeMillis(); for (int i=0; i<1000000; i++) { A a = new A(); a.doSomeThing(); } System.out.println(System.currentTimeMillis() - start); } public static void doReflection() throws Exception { long start = System.currentTimeMillis(); for (int i=0; i<1000000; i++) { A a = (A) Class.forName("misc.A").newInstance(); a.doSomeThing(); } System.out.println(System.currentTimeMillis() - start); } } 

इन परिणामों के साथ:

 35 // no reflection 465 // using reflection 

लुकअप को ध्यान में रखें और तत्काल एक साथ किया जाता है, और कुछ मामलों में लुकअप को दोबारा रिएक्ट किया जा सकता है, लेकिन यह सिर्फ एक बुनियादी उदाहरण है।

यहां तक ​​कि अगर आप बस इन्स्तांत, आप अभी भी एक प्रदर्शन हिट मिल:

 30 // no reflection 47 // reflection using one lookup, only instantiating 

दोबारा, वाईएमएमवी

हाँ, यह धीमी है

लेकिन याद रखना # 1 नियम – प्रीमेट्रूम ऑप्टीमाइजेशन सभी बुराइयों की जड़ है

(खैर, इसे सूखे के लिए # 1 से जोड़ा जा सकता है)

मैं कसम खाता हूँ, अगर कोई मुझसे काम पर आया और मुझसे पूछा कि मैं अगले कुछ महीनों के लिए अपने कोड पर बहुत सतर्क रहूंगा।

आपको तब तक अनुकूलित नहीं करना चाहिए जब तक आपको यह सुनिश्चित नहीं हो कि आपको इसकी आवश्यकता है, तब तक, बस अच्छा, पठनीय कोड लिखें

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

जब मुझे इस तरह के प्रश्न सुनते हैं तो यह मुझे बाहर की ओर झुकता है, लेकिन फिर मैं भूल जाता हूं कि सभी को स्वयं वास्तव में इसे प्राप्त करने से पहले सभी नियमों को सीखने से गुज़रना पड़ता है। आपके द्वारा "ऑप्टिमाइज़ किया गया" किसी व्यक्ति के डिबगिंग को बिगड़ने के बाद आप इसे प्राप्त करेंगे।

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

इस धागे में एक दिलचस्प बात हुई। # 1 उत्तर की जांच करें, यह एक उदाहरण है कि चीजों को अनुकूलित करने पर संकलक कितना शक्तिशाली है परीक्षण पूरी तरह अमान्य है क्योंकि गैर-चिंतनशील तात्कालिकता पूरी तरह से बाहर हो सकती है।

पाठ? जब तक आप एक स्वच्छ, बड़े करीने से कोडित समाधान नहीं लिखते हैं, तब तक कभी भी अनुकूलित न करें और यह बहुत धीमा हो।

आपको लगता है कि ए ए = नया A () JVM द्वारा अनुकूलित किया जा रहा है यदि आप ऑब्जेक्ट को एक सरणी में डालते हैं, तो वे अच्छी तरह से प्रदर्शन नहीं करते हैं। 😉 निम्नलिखित प्रिंट …

 new A(), 141 ns A.class.newInstance(), 266 ns new A(), 103 ns A.class.newInstance(), 261 ns public class Run { private static final int RUNS = 3000000; public static class A { } public static void main(String[] args) throws Exception { doRegular(); doReflection(); doRegular(); doReflection(); } public static void doRegular() throws Exception { A[] as = new A[RUNS]; long start = System.nanoTime(); for (int i = 0; i < RUNS; i++) { as[i] = new A(); } System.out.printf("new A(), %,d ns%n", (System.nanoTime() - start)/RUNS); } public static void doReflection() throws Exception { A[] as = new A[RUNS]; long start = System.nanoTime(); for (int i = 0; i < RUNS; i++) { as[i] = A.class.newInstance(); } System.out.printf("A.class.newInstance(), %,d ns%n", (System.nanoTime() - start)/RUNS); } } 

यह सुझाव है कि मेरी मशीन पर अंतर लगभग 150 एनएस है।

प्रतिबिंब वाला कुछ ऊपरी भाग है, लेकिन आधुनिक वीएम के मुकाबले इसे बहुत कम है, ऐसा करने के लिए इस्तेमाल किया जाता है।

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

"महत्वपूर्ण" संदर्भ पर पूरी तरह निर्भर है।

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

सामान्य रूप में, डिजाइन लचीलापन (जहां ज़रूरत होती है!) को आपके प्रतिबिंब के उपयोग को नहीं चलाना चाहिए, न कि प्रदर्शन। हालांकि, यह तय करने के लिए कि प्रदर्शन एक समस्या है, आपको चर्चा मंच से मनमानी प्रतिक्रिया प्राप्त करने की बजाय प्रोफ़ाइल की आवश्यकता है।

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

अनुप्रयोगों के कुछ उदाहरण जो कोड पीढ़ी का उपयोग करते हैं:

  • सीजीएलआईबी द्वारा उत्पन्न प्रॉक्सी के तरीकों को जोड़ना जावा की डायनामिक प्रॉक्सी से थोड़ी तेज़ है, क्योंकि सीजीआईबीबी अपने प्रॉक्सी के लिए बाइटकोड बनाता है, लेकिन गतिशील प्रॉक्सी केवल प्रतिबिंब ( मैं विधि कॉल में सीजीएलआईबी के बारे में लगभग 10x तेज है, लेकिन प्रॉक्सी बना रहा था धीमा था) का उपयोग करता है।

  • जेएसआरियल प्रतिबिंबित करने के बजाय क्रमबद्ध वस्तुओं के फ़ील्ड को पढ़ने / लिखने के लिए बाइटकोड बनाता है जेएसरियल की साइट पर कुछ मानक हैं।

  • मैं 100% निश्चित नहीं हूँ (और मुझे अब स्रोत पढ़ने की तरह महसूस नहीं है), लेकिन मुझे लगता है कि दिग्दर्शन इंजेक्शन करने के लिए Guice बाइट कोड उत्पन्न करता है। यदि मैं गलत हूं तो मुझे सही करों।

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

इस धागे में सूक्ष्मदर्शी चिह्नों को ध्यान से अवगत कराएं, इसलिए उन्हें नमक के एक अनाज के साथ लें। अब तक कम से कम त्रुटिपूर्ण है पीटर लॉरे: यह विधियों को जीतने के लिए गर्म हो जाता है, और यह (जानबूझकर) से बचने के विश्लेषण को समाप्त करने के लिए सुनिश्चित करता है कि आवंटन वास्तव में हो रहा है। यहां तक ​​कि इसकी एक समस्या भी है, हालांकि: उदाहरण के लिए, सरणी के बहुत सारे स्टोरों को कैश और स्टोर बफ़र्स को हरा देने की उम्मीद की जा सकती है, इसलिए यह आपके आवंटन बहुत तेज होने पर अधिकतर स्मृति बेंचमार्क हो जाएगा। (यद्यपि निष्कर्ष पर पहुंचने पर पीटर को यश कहते हैं: "2.5 गुणा" के बजाय अंतर "150 नं" है। मुझे संदेह है कि वह इस तरह के जीवन के लिए काम करता है।)

हाँ, प्रतिबिंब का उपयोग करते समय एक प्रदर्शन हिट हो गया है, लेकिन अनुकूलन के लिए संभावित समाधान विधि को कैशिंग कर रहा है:

  Method md = null; // Call while looking up the method at each iteration. millis = System.currentTimeMillis( ); for (idx = 0; idx < CALL_AMOUNT; idx++) { md = ri.getClass( ).getMethod("getValue", null); md.invoke(ri, null); } System.out.println("Calling method " + CALL_AMOUNT+ " times reflexively with lookup took " + (System.currentTimeMillis( ) - millis) + " millis"); // Call using a cache of the method. md = ri.getClass( ).getMethod("getValue", null); millis = System.currentTimeMillis( ); for (idx = 0; idx < CALL_AMOUNT; idx++) { md.invoke(ri, null); } System.out.println("Calling method " + CALL_AMOUNT + " times reflexively with cache took " + (System.currentTimeMillis( ) - millis) + " millis"); 

में परिणाम होगा:

[जावा] विधि कॉलिंग 1000000 बार reflexively लुकअप के साथ 5618 मिलियन लिया

[जावा] कॉलिंग विधि 1000000 गुना कैश के साथ reflexively 270 मिलियन लिया

हां, यह काफी धीमी है हम कुछ कोड चला रहे थे जो कि किया था, और जब मेरे पास इस समय उपलब्ध मीट्रिक नहीं है, तो अंतिम परिणाम यह था कि हमें प्रतिबिंब का उपयोग न करने के लिए उस कोड को दोबारा रिफ़क्टर करना पड़ा यदि आप जानते हैं कि कक्षा क्या है, तो सीधे कन्स्ट्रक्टर को कॉल करें।

दिलचस्प रूप से पर्याप्त, सेट अपसेट (सच), जो सुरक्षा जांच को छोड़ता है, की लागत में 20% की कमी है

सेट बिना पहुंच (सही)

 new A(), 70 ns A.class.newInstance(), 214 ns new A(), 84 ns A.class.newInstance(), 229 ns 

सेटअक्षम (सही) के साथ

 new A(), 69 ns A.class.newInstance(), 159 ns new A(), 85 ns A.class.newInstance(), 171 ns 

क्लास पर कॉल किए जाने वाले नए इंस्ट्रंस () के बजाय, क्लास। फोर्लाइमेन ("मिस्टरएसीए ए") की वजह से डर रिफेन्शन () ओवरहेड होता है (जिसे क्लास लुकअप की आवश्यकता होती है, संभवत: फाइल सिस्टम पर क्लास पथ को स्कैन करनी होती है)। मैं सोच रहा हूं कि आँकड़े क्या दिखते हैं यदि क्लास। ForName ("misc.A") को केवल एक बार लूप के बाहर किया जाता है, तो यह वास्तव में लूप के हर आमंत्रण के लिए नहीं किया जाता है।

हाँ, हमेशा धीमी गति से एक प्रतिबिंब के द्वारा एक वस्तु बनाएं क्योंकि JVM संकलन समय पर कोड का अनुकूलन नहीं कर सकता। अधिक जानकारी के लिए सूर्य / जावा प्रतिबिंब ट्यूटोरियल देखें।

यह सरल परीक्षण देखें:

 public class TestSpeed { public static void main(String[] args) { long startTime = System.nanoTime(); Object instance = new TestSpeed(); long endTime = System.nanoTime(); System.out.println(endTime - startTime + "ns"); startTime = System.nanoTime(); try { Object reflectionInstance = Class.forName("TestSpeed").newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } endTime = System.nanoTime(); System.out.println(endTime - startTime + "ns"); } } 

अक्सर आप अपाचे कॉमन्स बीन यूटील्स या प्रॉपर्टी यूटील्स का उपयोग कर सकते हैं जो आत्मनिरीक्षण (मूल रूप से वे कक्षाओं के बारे में मेटा डेटा को कैश करते हैं ताकि उन्हें प्रतिबिंब का उपयोग करने की आवश्यकता न हो)।

मुझे लगता है कि यह लक्ष्य / भारी लक्ष्य विधि है पर निर्भर करता है। यदि लक्ष्य विधि बहुत हल्का है (उदाहरण के लिए गेटर / सेटर), यह 1 ~ 3 गुना धीमा हो सकता है अगर लक्ष्य विधि 1 मिलीसेकेंड या ऊपर लेती है, तो प्रदर्शन बहुत करीब होगा यहां मैंने परीक्षण किया है जिसमें मैंने जावा 8 और प्रतिबिंबित किया था :

 public class ReflectionTest extends TestCase { @Test public void test_perf() { Profiler.run(3, 100000, 3, "m_01 by refelct", () -> Reflection.on(X.class)._new().invoke("m_01")).printResult(); Profiler.run(3, 100000, 3, "m_01 direct call", () -> new X().m_01()).printResult(); Profiler.run(3, 100000, 3, "m_02 by refelct", () -> Reflection.on(X.class)._new().invoke("m_02")).printResult(); Profiler.run(3, 100000, 3, "m_02 direct call", () -> new X().m_02()).printResult(); Profiler.run(3, 100000, 3, "m_11 by refelct", () -> Reflection.on(X.class)._new().invoke("m_11")).printResult(); Profiler.run(3, 100000, 3, "m_11 direct call", () -> X.m_11()).printResult(); Profiler.run(3, 100000, 3, "m_12 by refelct", () -> Reflection.on(X.class)._new().invoke("m_12")).printResult(); Profiler.run(3, 100000, 3, "m_12 direct call", () -> X.m_12()).printResult(); } public static class X { public long m_01() { return m_11(); } public long m_02() { return m_12(); } public static long m_11() { long sum = IntStream.range(0, 10).sum(); assertEquals(45, sum); return sum; } public static long m_12() { long sum = IntStream.range(0, 10000).sum(); assertEquals(49995000, sum); return sum; } } } 

पूरा परीक्षण कोड GitHub पर उपलब्ध है: ReflectionTest.java