2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
जावा मध्ये वस्तुनि heap स्मृतौ आवंटितानि सन्ति वा?
ठीकम्, अतीव अमूर्तम् अस्ति।
- public void test() {
- Object object = new Object();
- }
- 这个方法中的object对象,是在堆中分配内存么?
परिणामं वदतु: वस्तु स्तम्भे अथवा राशौ स्मृतिम् आवंटयितुं शक्नोति ।
अत्र मुख्यः बिन्दुः अस्ति : JVM इत्यस्य कार्यान्वयनस्य कृते JVM इत्यस्य कार्यक्षमतां सुधारयितुम् स्मृतिस्थानं रक्षितुं च JVM इत्यनेन “Escape analysis” इति विशेषता प्रदाति यत् वर्तमानकाले Escape analysis इति अपेक्षाकृतं अत्याधुनिकं अनुकूलनप्रौद्योगिकी अस्ति जावा वर्चुअल् मशीन्, तथा च JIT एकः अतीव महत्त्वपूर्णः अनुकूलन-प्रविधिः अपि अस्ति । jdk6 केवलं एतत् प्रौद्योगिकीम् प्रवर्तयितुं आरब्धवान्, jdk7 इत्यनेन पूर्वनिर्धारितरूपेण पलायनविश्लेषणं सक्षमं कर्तुं आरब्धम्, jdk8 इत्यनेन पूर्वनिर्धारितरूपेण पलायनविश्लेषणं सुदृढं कर्तुं आरब्धम्, तथा च JDK 9 पर्यन्तं पलायनविश्लेषणस्य उपयोगः पूर्वनिर्धारितरूपेण अनुकूलनविधिरूपेण भविष्यति, तथा च कोऽपि विशेषसंकलनमापदण्डः न भविष्यति अपेक्षिताः सन्ति।
अधुना "object may allocate memory on the heap" इति वाक्यं अवगच्छन्तु jdk7 इत्यस्मात् पूर्वं, अत्रत्याः object इत्यनेन jdk7 तथा 8 इत्यत्र heap इत्यत्र memory आवंटयितुं शक्यते, यतः jdk7 इत्यस्य उपरि memory आवंटनं कर्तुं शक्यते; केवलं Escape विश्लेषणं समर्थितं आरब्धम् अस्ति jdk9 अधिकतया स्टैक् इत्यत्र आवंटितम् अस्ति (अत्र वस्तु अतीव लघु अस्ति), यतः jdk9 केवलं पूर्वनिर्धारितरूपेण escape विश्लेषणं यथार्थतया समर्थयति सक्षमं च करोति
JIT संकलकानां (जस्ट-इन्-टाइम कम्पाइलर्) विकासेन तथा च पलायनविश्लेषणप्रौद्योगिक्याः क्रमिकपरिपक्वतायाः कारणेन, स्टैक् आवंटनं तथा स्केलर रिप्लेसमेण्ट् अनुकूलनप्रौद्योगिक्याः कारणात् "सर्ववस्तूनि ढेरे आवंटितानि भविष्यन्ति" In Java In इति न्यूनतया निरपेक्षतां प्राप्स्यति आभासीयन्त्रे, वस्तुनः राशेः स्मृतिः आवंटिताः भवन्ति, परन्तु विशेषः प्रकरणः अस्ति, अर्थात् यदि पलायनविश्लेषणानन्तरं ज्ञायते यत् कश्चन वस्तु विधितः न पलायते, तर्हि तत् स्तम्भे आवंटितुं अनुकूलितं भवितुम् अर्हति यदा विधिः निष्पादितः भवति यदा समाप्तं भवति तदा स्टैक् फ्रेम् पॉप् भवति तथा च ऑब्जेक्ट् मुक्तः भवति एतेन ढेरस्य उपरि स्मृतिः आवंटयितुं कचरासंग्रहणं कर्तुं च आवश्यकता न भवति ।हॉटस्पॉट् सम्प्रति एतत् न करोति).
JDK 6u23 (स्मरणीयं प्रमुखं संस्करणं JDK7) इत्यस्य अनन्तरं, Hotspot मध्ये पूर्वनिर्धारितरूपेण पलायनविश्लेषणं सक्षमं भवति यदि भवान् पूर्वसंस्करणस्य उपयोगं करोति तर्हि "-XX:+DoEscapeAnalysis Pass "-XX:+PrintEscapeAnalysis" इति विकल्पस्य माध्यमेन पलायनविश्लेषणं प्रदर्शयितुं शक्नोति । पलायनविश्लेषणार्थं फ़िल्टरपरिणामान् पश्यन्तु।
हॉटस्पॉट् पलायनविश्लेषणद्वारा स्केलरप्रतिस्थापनं कार्यान्वयति (अपलायितवस्तूनाम् स्केलरैः समुच्चयैः च प्रतिस्थापितं भवति, येन कोडदक्षतां सुधारयितुम् शक्यते), परन्तु अपलायितवस्तूनाम् अद्यापि राशेः स्मृतिः आवंटयिष्यन्ति, अतः अद्यापि वक्तुं शक्यते यत् सर्वाणि वस्तूनि Allocate इति स्मृतिः राशौ उपरि।
तदतिरिक्तं Open JDK इत्यस्य आधारेण गहनतया अनुकूलितम्ताओबाओ वि.एम, येषु अभिनवः GCIH (GC invisible heap) प्रौद्योगिकी off-heap कार्यान्वयति, दीर्घजीवनचक्रयुक्तानि वस्तूनि ढेरात् बहिः यावत् स्थानान्तरयति, तथा च GC GCIH अन्तः Java वस्तुनः प्रबन्धनं न करोति, तस्मात् GC पुनःप्रयोगस्य आवृत्तिः न्यूनीकरोति तथा च The purpose इत्यत्र सुधारं करोति जीसी पुनर्प्राप्ति दक्षता के।
स्त्राव: यदा प्रत्येकं मेथड् निष्पादितं भवति तदा स्थानीयचरसारणी, ऑपरेशनस्टैक्स्, डायनामिक कनेक्शन्स्, मेथड् निर्गमनम् इत्यादीनां सूचनानां संग्रहणार्थं एकस्मिन् समये स्टैक् फ्रेम निर्मितं भविष्यति प्रत्येकं विधितः आह्वानं क्रियमाणात् यावत् निष्पादनं समाप्तं भवति तावत् प्रक्रिया आभासीयन्त्रस्य स्तम्भे स्टैक् मध्ये धक्कायितुं यावत् स्टैक् फ्रेमस्य प्रक्रियायाः अनुरूपं भवति
राशः : १.यदा वस्तु उदाहरणं भवति तदा वस्तु राशौ आवंटितं भवति तथा च राशौ सन्दर्भं स्तम्भे धक्कायते ।
परिभ्रंशति:यदा कस्यचित् वस्तुनः सूचकः बहुविधैः विधिभिः वा धागैः वा सन्दर्भितः भवति तदा वयं वदामः यत् सूचकः सामान्यतया पलायते, वस्तुनि, वैश्विकचराः च सामान्यतया पलायन्ते ।
पलायनविश्लेषणम् : १.अस्याः पलायनघटनायाः विश्लेषणार्थं प्रयुक्ता पद्धतिः पलायनविश्लेषणम् इति कथ्यते
पलायन विश्लेषण अनुकूलनम् - ढेरस्य उपरि आवंटनम्:स्टैक् इत्यत्र आवंटनस्य अर्थः अस्ति यत् मेथड् इत्यस्मिन् स्थानीयचरेन उत्पन्नं दृष्टान्तं (कोऽपि एस्केप् न भवति) स्टैक् इत्यत्र आवंटनं भवति तथा च आवंटनस्य समाप्तेः अनन्तरं कॉल् स्टैक् इत्यत्र निष्पादनं निरन्तरं भवति अन्ते सूत्रस्य समाप्तिः भवति, स्तम्भस्थानं पुनः प्रयुज्यते, स्थानीय Variable वस्तुनि अपि पुनः प्रयुज्यन्ते ।
उत्तरम् - न अवश्यम्।
यदि पलायनविश्लेषणस्य शर्ताः पूर्यन्ते तर्हि स्तम्भे वस्तु आवंटयितुं शक्यते ।ढेरस्मृतिविनियोगं GC दबावं च न्यूनीकरोतु।यतः स्तम्भस्मृतिः सीमितं भवति, यदि वस्तु स्केलरप्रतिस्थापनस्य शर्ताः पूरयति तर्हिविषयस्य भागेषु विभज्य अपरं शल्यक्रिया क्रियते ।स्केलर प्रतिस्थापनस्य विशिष्टा पद्धतिः अस्ति यत्: JVM वस्तुं अधिकं विभज्य वस्तुं एतया पद्धत्या प्रयुक्तेषु अनेकसदस्यचरेषु विघटयिष्यतिएवं स्टैक् मेमोरी तथा रजिस्टर्स् इत्येतयोः उत्तमप्रयोगस्य लक्ष्यं सिद्धं भवति ।
इदं एकं पार-कार्यं वैश्विकं आँकडाप्रवाहविश्लेषणं एल्गोरिदम् अस्ति यत् जावा कार्यक्रमेषु समन्वयनभारं स्मृतिराशिविनियोगदाबं च प्रभावीरूपेण न्यूनीकर्तुं शक्नोति । पलायनविश्लेषणस्य माध्यमेन जावा हॉटस्पॉट् संकलकः नूतनस्य वस्तुनः सन्दर्भस्य उपयोगपरिधिं विश्लेषितुं शक्नोति तथा च एतत् वस्तु ढेरं प्रति आवंटयितुं शक्नोति वा इति निर्णयं कर्तुं शक्नोति ।
पलायनविश्लेषणस्य मूलभूतव्यवहारः वस्तुनां गतिशीलव्याप्तेः विश्लेषणं भवति :
सङ्गणकभाषासंकलकअनुकूलनसिद्धान्ते पलायनविश्लेषणं सूचकानाम् गतिशीलपरिधिविश्लेषणस्य पद्धतिं निर्दिशति एतत् संकलकअनुकूलनसिद्धान्तस्य सूचकविश्लेषणेन आकारविश्लेषणेन च सम्बद्धम् अस्ति यदा मेथड् मध्ये चरः (अथवा ऑब्जेक्ट्) आवंटितः भवति तदा तस्य सूचकः वैश्विकरूपेण प्रत्यागन्तुं वा सन्दर्भितः वा भवितुम् अर्हति, यत् अन्यैः मेथड् वा थ्रेड् इत्यनेन सन्दर्भितं भविष्यति । सामान्यजनस्य शब्देषु, यदि कस्यचित् वस्तुनः सूचकः बहुविधैः विधिभिः वा धागैः वा सन्दर्भितः भवति, तर्हि वयं वस्तुनः सूचकं (अथवा वस्तु) Escape इति वदामः (यतोहि अस्मिन् समये, वस्तु विधिस्य अथवा धागस्य, स्थानीयव्याप्तेः पलायनं करोति)
संक्षिप्तं विवरणम्: "पलायनविश्लेषणम्: एकं स्थिरं विश्लेषणं यत् सूचकानाम् गतिशीलपरिधिं निर्धारयति। एतत् विश्लेषणं कर्तुं शक्नोति यत् कार्यक्रमे सूचकं कुत्र अभिगन्तुं शक्यते।" नवनिर्मितं वस्तु पलायते।
वस्तु पलायते वा इति निर्धारयितुं न्याय्यसमयसंकलनस्य आधारः : एकं वस्तु राशौ (राशिस्थस्य वस्तुनः स्थिरक्षेत्रं वा दृष्टान्तक्षेत्रं वा) संगृहीतं वा इति, अपरं च वस्तु अन्तर्गतं भवति वा इति अज्ञात कोड।
एस्केप एनालिसिस इत्येतत् सम्प्रति जावा वर्चुअल् मशीनेषु अपेक्षाकृतं अत्याधुनिकं अनुकूलनप्रौद्योगिकी अस्ति यथा प्रकारस्य उत्तराधिकारसम्बन्धविश्लेषणम्, इदं प्रत्यक्षतया कोडस्य अनुकूलनस्य साधनं नास्ति, अपितु अन्यस्य अनुकूलनसाधनानाम् आधारं प्रदाति इति विश्लेषणप्रौद्योगिकी अस्ति
पलायनविश्लेषणम् : एषा अतीव महत्त्वपूर्णा JIT अनुकूलनप्रौद्योगिकी अस्ति, यस्य उपयोगः पद्धत्याः बहिः वस्तु अभिगमिष्यति वा इति निर्धारयितुं अर्थात् पद्धतेः व्याप्तेः पलायनार्थं भवति Escape analysis JIT compiler इत्यस्य एकं सोपानम् अस्ति JIT इत्यस्य माध्यमेन वयं निर्धारयितुं शक्नुमः यत् केषां ऑब्जेक्ट् इत्यस्य उपयोगः मेथड् इत्यस्य अन्तः कर्तुं शक्यते तथा च बहिः एस्केप् कर्तुं न शक्यते, यथा heap इत्यस्य स्थाने stack इत्यत्र आवंटनं कर्तुं शक्यते .अथवा भण्डारणार्थं वस्तुनः बहुषु मूलभूतप्रकारेषु विभक्तुं स्केलरप्रतिस्थापनं कुर्वन्तु । इदं एकं पार-कार्यं वैश्विकं आँकडाप्रवाहविश्लेषणं एल्गोरिदम् अस्ति यत् जावा कार्यक्रमेषु समन्वयनभारं स्मृतिराशिविनियोगं च कचरासंग्रहणदाबं च प्रभावीरूपेण न्यूनीकर्तुं शक्नोति पलायनविश्लेषणस्य माध्यमेन जावा हॉटस्पॉट् संकलकः नूतनस्य वस्तुनः सन्दर्भस्य उपयोगपरिधिं विश्लेषितुं शक्नोति तथा च एतत् वस्तु ढेरं प्रति आवंटयितुं शक्नोति वा इति निर्णयं कर्तुं शक्नोति ।
पलायनविश्लेषणं मुख्यतया स्थानीयचरानाम् उपरि केन्द्रितं भवति यत् निर्धारयति यत् राशे आवंटितवस्तूनि पद्धतेः व्याप्तेः पलायिताः सन्ति वा इति । इदं संकलक-अनुकूलन-सिद्धान्तानां सूचक-विश्लेषणेन, आकार-विश्लेषणेन च सम्बद्धम् अस्ति । यदा मेथड् मध्ये चरः (अथवा ऑब्जेक्ट्) आवंटितः भवति तदा तस्य सूचकः वैश्विकरूपेण प्रत्यागन्तुं वा सन्दर्भितः वा भवितुम् अर्हति, यत् अन्यैः मेथड् वा थ्रेड् इत्यनेन सन्दर्भितं भविष्यति । सामान्यजनस्य शब्देषु यदि कस्यचित् वस्तुनः सूचकः बहुविधैः धागैः वा सन्दर्भितः भवति तर्हि वयं वदामः यत् वस्तुनः सूचकः पलायितः अस्ति । कोडसंरचनायाः, आँकडाप्रयोगस्य च सम्यक् डिजाइनं कृत्वा कार्यक्रमस्य कार्यक्षमतायाः अनुकूलनार्थं पलायनविश्लेषणस्य उत्तमं उपयोगं कर्तुं शक्यते । वयं राशेः उपरि वस्तुनां आवंटनस्य उपरिभारं न्यूनीकर्तुं शक्नुमः तथा च पलायनविश्लेषणद्वारा स्मृतिप्रयोगं सुधारयितुम् अर्हति ।
पलायनविश्लेषणं कश्चन वस्तु स्वजीवनकाले पद्धतेः व्याप्तेः बहिः पलायितवान् वा इति निर्धारयितुं प्रयुक्ता । जावा विकासे, तत्सम्बद्धं अनुकूलनं कर्तुं तथा कार्यक्रमस्य कार्यक्षमतां स्मृति-उपयोगदक्षतां च सुधारयितुम्, वस्तुनां जीवनचक्रं व्याप्तिञ्च निर्धारयितुं पलायन-विश्लेषणस्य उपयोगः भवति
यदा वस्तु निर्मीयते तदा तस्य उपयोगः विधिस्य अन्तः कर्तुं शक्यते, अथवा अन्येषु विधिषु सूत्रेषु वा पारितं कृत्वा विधितः बहिः निरन्तरं विद्यते यदि वस्तु विधिस्य व्याप्तेः पलायनं न करोति तर्हि JVM तत् राशस्य स्थाने ढेरस्य उपरि आवंटनं कर्तुं शक्नोति, अतः राशस्मृतिविनियोगस्य कचरासङ्ग्रहस्य च उपरिभारं परिहरति
- 关于逃逸分析的论文在1999年就已经发表,但直到Sun JDK 1.6才实现了逃逸分析,而且直到现在这项优化尚未足够成熟,仍有很大的改进余地。不成熟的原因主要是不能保证逃逸分析的性能收益必定高于它的消耗。如果要完全准确的判断一个对象是否会逃逸,需要进行数据流敏感的一系列复杂分析,从而确定程序各个分支执行时对此对象的影响。这是一个相对高耗时的过程,如果分析完后发现没有几个不逃逸的对象,那这些运行期耗用的时间就白白浪费了,所以目前虚拟机只能采用不那么准确,但时间压力相对较小的算法来完成逃逸分析。还有一点是,基于逃逸分析的一些优化手段,如上面提到的“栈上分配”,由于HotSpot虚拟机目前的实现方式导致栈上分配实现起来比较复杂,因此在HotSpot中暂时还没有做这项优化。
- 在测试结果中,实施逃逸分析后的程序在MicroBenchmarks中往往能运行出不错的成绩,但是在实际的应用程序,尤其是大型程序中反而发现实施逃逸分析可能出现效果不稳定的情况,或因分析过程耗时但却无法有效判别出非逃逸对象而导致性能(即使编译的收益)有所下降,所以在很长的一段时间里,即使是Server Compiler,也默认不开启逃逸分析(在JDK 1.6 Update 23的Server Compiler中才开始默认开启了逃逸分析),甚至在某些版本(如JDK 1.6 Update 18)中还曾经短暂的完全禁止了这项优化。
- 如果有需要,并且确认对程序运行有益,用户可以使用参数-XX:+DoEscapeAnalysis来手动开启逃逸分析,开启之后可以通过参数-XX:+PrintEscapeAnalysis来查看分析结果。有了逃逸分析支持之后,用户可以使用参数-XX:EliminateAllocations来开启标量替换,使用+XX:+EliminateLocks来开启同步消除,使用参数-XX:PrintEliminateAllocations查看标量的替换情况。
- 尽管目前逃逸分析的技术仍不是十分成熟,但是他却是即时编译器优化技术的一个重要的方向,在今后的虚拟机中,逃逸分析技术肯定会支撑起一系列使用有效的优化技术。
JVM पलायनविश्लेषणस्य मूलभूतं सिद्धान्तं स्थिरं गतिशीलं च द्वयोः विश्लेषणविधियोः माध्यमेन वस्तुनः पलायनस्थितिं निर्धारयितुं भवति ।
जावा-संकलन-प्रणाल्यां जावा-स्रोत-सङ्केत-सञ्चिकां सङ्गणक-निष्पादनीय-यन्त्र-निर्देशे परिणतुं प्रक्रियायां संकलनस्य द्वौ चरणौ आवश्यकौ भवतः ।
संकलनस्य प्रथमः खण्डः अग्रे-अन्त-संकलकं निर्दिशति.java सञ्चिकापरिवर्तितः इति.वर्गसञ्चिका (बाइटकोड् सञ्चिका)। अग्र-अन्त-संकलक-उत्पादाः JDK इत्यस्य Javac अथवा Eclipse JDT इत्यस्मिन् वृद्धिशीलः संकलकः भवितुम् अर्हन्ति ।
द्वितीयसंकलनपदे JVM बाइटकोड् व्याख्याय तत्सम्बद्धेषु यन्त्रनिर्देशेषु अनुवादयति, बाइटकोड् मध्ये एकैकं पठति, एकैकशः व्याख्यानं कृत्वा यन्त्रसङ्केते अनुवादयति च
स्पष्टतया, व्याख्यायाः मध्यवर्तीप्रक्रियायाः कारणात् तस्य निष्पादनवेगः निष्पादनीयस्य द्विचक्रीयबाइटकोड्कार्यक्रमस्य अपेक्षया बहु मन्दः भविष्यति इति अनिवार्यम् एतत् पारम्परिकस्य JVM व्याख्याकारस्य (Interpreter) कार्यम् अस्ति ।
एतस्याः दक्षतासमस्यायाः समाधानार्थं JIT (Just In Time Compiler) इति प्रौद्योगिकी प्रवर्तते स्म ।
JIT प्रौद्योगिक्याः आरम्भानन्तरं जावा-प्रोग्रामाः अद्यापि व्याख्याकारस्य माध्यमेन व्याख्याय निष्पादिताः भवन्ति अर्थात् मुख्यशरीरस्य व्याख्या अद्यापि निष्पादिता च भवति, परन्तु मध्यवर्तीलिङ्काः आंशिकरूपेण निष्कासिताः भवन्ति
JIT Compiler (Just-in-timeCompiler) केवलं समये संकलनम्। प्रारम्भिकं जावा कार्यान्वयनसमाधानं अनुवादकानां (व्याख्याकारानाम्) समुच्चयः आसीत् यत् प्रत्येकं जावानिर्देशं समतुल्यसूक्ष्मप्रोसेसरनिर्देशे अनुवादयति स्म, तथा च अनुवादितनिर्देशानां क्रमानुसारं क्रमेण निष्पादयति स्म, यतः जावानिर्देशः एकदर्जनं वा दर्जनशः वा अनुवादं कर्तुं शक्नोति स्म समतुल्य सूक्ष्मसंसाधकनिर्देशाः, एषः मोडः अतीव मन्दं निष्पादयति ।
यदा JVM पश्यति यत् कश्चन विधिः अथवा कोडखण्डः विशेषतया बहुधा चालितः अस्ति तदा सः तत् "Hot Spot Code" इति मन्यते । ततः JIT "hot code" इत्यस्य भागं स्थानीययन्त्रेण सह सम्बद्धे यन्त्रसङ्केते अनुवादयिष्यति, तस्य अनुकूलनं करिष्यति, ततः अनुवादितं यन्त्रसङ्केतं अग्रिमप्रयोगाय संग्रहयिष्यति ।
अनुवादितं यन्त्रसङ्केतं कुत्र संग्रहणीयम् ? एतत् सञ्चयं Code Cache इति उच्यते । द्रष्टुं शक्यते यत् JVM तथा WEB अनुप्रयोगयोः उच्चसमकालीनतां प्राप्तुं पद्धतयः समानाः सन्ति, तथापि ते cache architecture इत्यस्य उपयोगं कुर्वन्ति ।
यदा JVM अग्रिमे समये समानं उष्णसङ्केतं सम्मुखीभवति तदा व्याख्यायाः मध्यवर्तीलिङ्कं लङ्घयति, यन्त्रसङ्केतं प्रत्यक्षतया Code Cache तः लोड् करोति, पुनः संकलनं विना प्रत्यक्षतया निष्पादयति च
अतः JIT इत्यस्य समग्रं लक्ष्यं हॉट् कोड् इत्यस्य आविष्कारः अस्ति, तथा च हॉट् कोड् इत्यस्य कार्यप्रदर्शनस्य उन्नयनस्य कुञ्जी अभवत् ।
अतः जेवीएम इत्यस्य समग्ररणनीतिः अस्ति : १.
अधिकांशस्य असामान्यसङ्केतानां कृते अस्माकं तान् यन्त्रसङ्केतेषु संकलितुं समयं व्ययितुं आवश्यकता नास्ति, अपितु व्याख्याननिष्पादनद्वारा च चालयितुं आवश्यकता वर्तते;
अपरपक्षे, केवलं लघुभागं गृह्णाति इति उष्णसङ्केतस्य कृते आदर्शं चालनवेगं प्राप्तुं यन्त्रसङ्केते संकलितुं शक्नुमः ।
JIT (just in time compilation) इत्यस्य उद्भवः व्याख्याकारानाम् अन्तरं च
(1) व्याख्याकारः बाइटकोड् इत्यस्य व्याख्यां यन्त्रसङ्केते करोति यद्यपि अग्रिमे समये समानं बाइटकोड् सम्मुखीभवति तथापि पुनः पुनः व्याख्यां करिष्यति ।
(2) JIT केचन बाइटकोड् यन्त्रसङ्केतेषु संकलितं करोति तथा च तान् Code Cache मध्ये संग्रहयति यदा अग्रिमे समये समानं कोडं सम्मुखीभवति तदा पुनः संकलनं विना प्रत्यक्षतया निष्पादितं भविष्यति ।
(३) व्याख्याकारः बाइटकोड् इत्यस्य व्याख्यां यन्त्रसङ्केतरूपेण करोति यत् सर्वेषां मञ्चानां सामान्यम् अस्ति ।
(4) JIT मञ्चप्रकारस्य आधारेण मञ्चविशिष्टयन्त्रसङ्केतं जनयिष्यति।
JVM इत्यत्र बहुविधाः जस्ट-इन्-टाइम-कम्पैलराः सन्ति, मुख्यतया C1 तथा C2, तथा च Graal (प्रयोगात्मकम्) ।
बहुविधाः जस्ट्-इन्-टाइम् कम्पैलर्स् बाइटकोड् इत्यस्य अनुकूलनं करिष्यन्ति तथा च मशीन् कोड् जनयिष्यन्ति
JVM निष्पादनस्थितिं ५ स्तरेषु विभजति:
स्तर 0, व्याख्याकार
स्तरः १, C1 just-in-time compiler (प्रोफाइलिंग् विना) इत्यस्य उपयोगेन संकलितः निष्पादितः च ।
स्तर 2, C1 just-in-time compiler (मूलभूत-प्रोफाइलिंगेन सह) इत्यस्य उपयोगेन संकलितं निष्पादितं च
स्तर 3, C1 just-in-time compiler इत्यस्य उपयोगेन संकलितं निष्पादितं च (पूर्णप्रोफाइलिंगेन सह)
स्तरः ४, C2 just-in-time compiler इत्यस्य उपयोगेन संकलितः निष्पादितः च
JVM प्रत्यक्षतया C2 सक्षमं न करिष्यति तस्य स्थाने, प्रथमं C1 संकलनद्वारा कार्यक्रमस्य चालनस्थितिं संग्रहयति, ततः विश्लेषणपरिणामानां आधारेण C2 सक्षमं कर्तव्यं वा इति निर्धारयति ।
स्तरितसंकलनविधाने आभासीयन्त्रनिष्पादनस्थितिः सरलतः जटिलपर्यन्तं, द्रुततः मन्दपर्यन्तं पञ्चस्तरयोः विभक्तं भवति ।
संकलनस्य समये प्रक्रियां त्वरितुं हॉट् कोड् कैशिंग् इत्यस्य अतिरिक्तं JIT कोड् इत्यस्य उपरि अनेकानि अनुकूलनानि अपि करिष्यति ।
केषाञ्चन अनुकूलनानां उद्देश्यं भवति यत्...स्मृतिराशिविनियोगदाबं न्यूनीकरोतु , JIT अनुकूलने महत्त्वपूर्णेषु तकनीकेषु एकं पलायनविश्लेषणम् इति कथ्यते । पलायनविश्लेषणस्य अनुसारं जस्ट्-इन्-टाइम-संकलकः संकलनप्रक्रियायाः समये निम्नलिखितरूपेण कोडं अनुकूलितं करिष्यति ।
एतत् कोडस्य स्थिरसंरचनायाः परीक्षणं करोति यत् वस्तु पलायितुं शक्नोति वा इति निर्धारयति । यथा, यदा कश्चन वस्तु कस्यचित् वर्गस्य सदस्यचरस्य कृते नियुक्तः भवति अथवा बाह्यविधिं प्रति प्रत्यागच्छति तदा वस्तु पलायते इति निर्धारयितुं शक्यते ।
विधि-आह्वानस्य, वस्तु-सन्दर्भस्य च व्यवहारं अवलोक्य कश्चन वस्तु पलायते वा इति निर्धारयति । यथा - यदा कश्चन वस्तु बहुसूत्रैः सन्दर्भितः भवति तदा वस्तु पलायितः इति न्याययितुं शक्यते ।
पलायनविश्लेषणं कोडस्य गहनविश्लेषणं करोति यत् एतत् निर्धारयति यत् विधिस्य आयुषः कालखण्डे वस्तु विधिव्याप्तेः बहिः पलायिता वा इति । यदि वस्तु न पलायते तर्हि JVM तत् राशेः स्थाने स्तम्भे आवंटयितुं शक्नोति ।
वस्तुनः त्रीणि पलायन अवस्थाः सन्ति : वैश्विकपलायनम्, पैरामीटर् पलायनम्, पलायनं च नास्ति ।
वैश्विक पलायन(GlobalEscape): अर्थात् वर्तमान मेथड् अथवा वर्तमान थ्रेड् इत्यस्मात् वस्तुनः व्याप्तिः पलायते ।
सामान्यतया निम्नलिखित परिदृश्यानि सन्ति ।
1 वस्तु स्थिरचरम् अस्ति
२ वस्तु पलायितवस्तु
3 वर्तमान मेथड् इत्यस्य रिटर्न् वैल्यू इत्यस्य रूपेण ऑब्जेक्ट् इत्यस्य उपयोगः भवति
पैरामीटर् पलायन(ArgEscape): अर्थात्, कश्चन वस्तु विधि-पैरामीटर्-रूपेण पारितः भवति अथवा पैरामीटर्-द्वारा सन्दर्भितः भवति, परन्तु आह्वान-प्रक्रियायाः समये कोऽपि वैश्विकः पलायनः न भवति ।
न पलायनम्: विधिस्थः विषयः न पलायते इति यावत् ।
पलायन अवस्था नमूनासङ्केतः निम्नलिखितरूपेण अस्ति ।
- public class EscapeAnalysisTest {
-
- public static Object globalVariableObject;
-
- public Object instanceObject;
-
- public void globalVariableEscape(){
- globalVariableObject = new Object(); // 静态变量,外部线程可见,发生逃逸
- }
-
- public void instanceObjectEscape(){
- instanceObject = new Object(); // 赋值给堆中实例字段,外部线程可见,发生逃逸
- }
-
- public Object returnObjectEscape(){
- return new Object(); // 返回实例,外部线程可见,发生逃逸
- }
-
- public void noEscape(){
- Object noEscape = new Object(); // 仅创建线程可见,对象无逃逸
- }
-
- }
1. मेथड् एस्केप् : मेथड् बॉडी इत्यस्मिन् स्थानीयचरं परिभाषयन्तु, यस्य सन्दर्भः बाह्यविधिना भवितुं शक्नोति, यथा मेथड् इत्यत्र कॉलिंग् पैरामीटर् इत्यस्य रूपेण पारितः भवति, अथवा प्रत्यक्षतया ऑब्जेक्ट् इत्यस्य रूपेण प्रत्यागच्छति अथवा, विषयः विधितः बहिः प्लवति इति गम्यते ।
विधिपलायनेषु अन्तर्भवन्ति : १.
- 我们可以用下面的代码来表示这个现象。
-
- //StringBuffer对象发生了方法逃逸
- public static StringBuffer createStringBuffer(String s1, String s2) {
- StringBuffer sb = new StringBuffer();
- sb.append(s1);
- sb.append(s2);
- return sb;
- }
- 上面的例子中,StringBuffer 对象通过return语句返回。
-
- StringBuffer sb是一个方法内部变量,上述代码中直接将sb返回,这样这个StringBuffer有可能被其他方法所改变,这样它的作用域就不只是在方法内部,虽然它是一个局部变量,称其逃逸到了方法外部。
-
- 甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸。
-
- 不直接返回 StringBuffer,那么StringBuffer将不会逃逸出方法。
-
- 具体的代码如下:
-
- // 非方法逃逸
- public static String createString(String s1, String s2) {
- StringBuffer sb = new StringBuffer();
- sb.append(s1);
- sb.append(s2);
- return sb.toString();
- }
- 可以看出,想要逃逸方法的话,需要让对象本身被外部调用,或者说, 对象的指针,传递到了 方法之外。
कथं शीघ्रं निर्धारयितुं शक्यते यत् पलायनविश्लेषणं जातम् वा?
- public class EscapeAnalysis {
-
- public EscapeAnalysis obj;
-
- /**
- * 方法返回EscapeAnalysis对象,发生逃逸
- * @return
- */
- public EscapeAnalysis getInstance() {
- return obj == null ? new EscapeAnalysis():obj;
- }
-
- /**
- * 为成员属性赋值,发生逃逸
- */
- public void setObj() {
- this.obj = new EscapeAnalysis();
- }
-
- /**
- * 对象的作用于仅在当前方法中有效,没有发生逃逸
- */
- public void useEscapeAnalysis() {
- EscapeAnalysis e = new EscapeAnalysis();
- }
-
- /**
- * 引用成员变量的值,发生逃逸
- */
- public void useEscapeAnalysis2() {
- EscapeAnalysis e = getInstance();
- }
- }
2. थ्रेड् एस्केप् : एतत् वस्तु अन्यैः थ्रेड्-द्वारा अभिगम्यते, यथा इन्स्टन्स्-चराय नियुक्तं अन्यैः थ्रेड्-इत्यनेन च अभिगम्यते । वस्तु वर्तमानसूत्रात् पलायितवान् ।
पलायनविश्लेषणं जावाकार्यक्रमेषु निम्नलिखितअनुकूलनरणनीतयः आनेतुं शक्नोति: ढेरस्य उपरि आवंटनं, समन्वयननिराकरणं, स्केलरप्रतिस्थापनं, विधि-इन्लाइनिंग् च;
पलायन विश्लेषणसम्बद्धाः मापदण्डाः : १.
- -XX:+DoEscapeAnalysis 开启逃逸分析
- -XX:+PrintEscapeAnalysis 开启逃逸分析后,可通过此参数查看分析结果。
- -XX:+EliminateAllocations 开启标量替换
- -XX:+EliminateLocks 开启同步消除
- -XX:+PrintEliminateAllocations 开启标量替换后,查看标量替换情况。
पलायनविश्लेषणेन निर्धारयितुं शक्यते यत् के वस्तुनः विधिस्य व्याप्तेः पलायनं न करिष्यन्ति तथा च एतानि वस्तुनि राशेः स्थाने स्तम्भे आवंटयितुं शक्नुवन्ति । स्टैक् इत्यत्र आवंटितानि वस्तूनि कचरासंग्रहणं विना मेथड् कॉल् जीवनचक्रस्य अन्तः निर्मिताः नष्टाः च भवन्ति, अतः कार्यक्रमस्य निष्पादनदक्षतायां सुधारः भवति
सामान्यपरिस्थितौ ये वस्तूनि पलायितुं न शक्नुवन्ति ते तुल्यकालिकरूपेण विशालं स्थानं गृह्णन्ति यदि स्तम्भे स्थानं उपयोक्तुं शक्यते तर्हि विधिः समाप्तः भवति तदा बहूनां वस्तूनि नष्टानि भविष्यन्ति, येन जीसी-दाबः न्यूनीकरोति
ढेरे आवंटनविचाराःस्टैक् इत्यत्र आवंटनं JVM द्वारा प्रदत्तं अनुकूलनप्रौद्योगिकी अस्ति ।
विचारः अस्ति यत् - १.
समस्या : यतः स्तम्भस्मृतिः तुल्यकालिकरूपेण लघुः भवति, तस्मात् बृहत्वस्तूनि स्तम्भे आवंटनार्थं उपयुक्तानि न भवन्ति, न च ।
ऑन-स्टैक् आवंटनं सक्षमं कुर्वन्तु
स्टैक् इत्यत्र आवंटनं पलायनविश्लेषणं स्केलरप्रतिस्थापनं च आधारितं भवति, अतः पलायनविश्लेषणं स्केलरप्रतिस्थापनं च सक्षमं भवितुमर्हति अवश्यं, JDK1.8 पूर्वनिर्धारितरूपेण सक्षमम् अस्ति ।
- 开启逃逸分析:-XX:+DoEscapeAnalysis
- 关闭逃逸分析:-XX:-DoEscapeAnalysis
- 显示分析结果:-XX:+PrintEscapeAnalysis
-
-
- 开启标量替换:-XX:+EliminateAllocations
- 关闭标量替换:-XX:-EliminateAllocations
- 显示标量替换详情:-XX:+PrintEliminateAllocations
स्टैक् इत्यत्र आवंटनस्य उदाहरणम् : १.
- 示例1
- import java.lang.management.ManagementFactory;
- import java.util.List;
- /**
- * 逃逸分析优化-栈上分配
- * 栈上分配,意思是方法内局部变量(未发生逃逸)生成的实例在栈上分配,不用在堆中分配,分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量对象也被回收。
- * 一般生成的实例都是放在堆中的,然后把实例的指针或引用压入栈中。
- *虚拟机参数设置如下,表示做了逃逸分析 消耗时间在10毫秒以下
- * -server -Xmx10M -Xms10M
- -XX:+DoEscapeAnalysis -XX:+PrintGC
- *
- *虚拟机参数设置如下,表示没有做逃逸分析 消耗时间在1000毫秒以上
- * -server -Xmx10m -Xms10m
- -XX: -DoEscapeAnalysis -XX:+PrintGC
- * @author 734621
- *
- */
-
- public class OnStack{
- public static void alloc(){
- byte[] b=new byte[2];
- b[0]=1;
- }
- public static void main(String [] args){
- long b=System.currentTimeMillis();
- for(int i=0;i<100000000;i++){
- alloc();
- }
- long e=System.currentTimeMillis();
- System.out.println("消耗时间为:" + (e - b));
- List<String> paramters = ManagementFactory.getRuntimeMXBean().getInputArguments();
- for(String p : paramters){
- System.out.println(p);
- }
- }
- }
-
-
- 加逃逸分析的结果
- [GC (Allocation Failure) 2816K->484K(9984K), 0.0013117 secs]
- 消耗时间为:7
- -Xmx10m
- -Xms10m
- -XX:+DoEscapeAnalysis
- -XX:+PrintGC
-
-
-
- 没有加逃逸分析的结果如下:
- [GC (Allocation Failure) 3320K->504K(9984K), 0.0003174 secs]
- [GC (Allocation Failure) 3320K->504K(9984K), 0.0002524 secs]
- 消耗时间为:1150
- -Xmx10m
- -Xms10m
- -XX:-DoEscapeAnalysis
- -XX:+PrintGC
-
-
- 以上测试可以看出,栈上分配可以明显提高效率: 效率是不开启的1150/7= 160倍
-
-
- 示例2
- 我们通过举例来说明 开启逃逸分析 和 未开启逃逸分析时候的情况
-
- class User {
- private String name;
- private String age;
- private String gender;
- private String phone;
- }
- public class StackAllocation {
- public static void main(String[] args) throws InterruptedException {
- long start = System.currentTimeMillis();
- for (int i = 0; i < 100000000; i++) {
- alloc();
- }
- long end = System.currentTimeMillis();
- System.out.println("花费的时间为:" + (end - start) + " ms");
-
- // 为了方便查看堆内存中对象个数,线程sleep
- Thread.sleep(10000000);
- }
-
- private static void alloc() {
- // 未发生逃逸
- User user = new User();
- }
- }
- 设置JVM参数,表示未开启逃逸分析
- -Xmx1G -Xms1G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails
- 花费的时间为:664 ms
- 然后查看内存的情况,发现有大量的User存储在堆中
-
- 开启逃逸分析
- -Xmx1G -Xms1G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails
- 然后查看运行时间,我们能够发现花费的时间快速减少,同时不会发生GC操作
- 花费的时间为:5 ms
- 在看内存情况,我们发现只有很少的User对象,说明User未发生逃逸,因为它存储在栈中,随着栈的销毁而消失。
तुलनेन वयं द्रष्टुं शक्नुमः
पलायनविश्लेषणेन ज्ञातव्यं यत् केचन वस्तूनि केवलं एकेन सूत्रेण एव अभिगम्यन्ते, अन्यसूत्रेषु न पलायते । अतः अनावश्यकसमन्वयनक्रियाः समाप्तुं शक्यन्ते तथा च बहु-धागायुक्तानां कार्यक्रमानां निष्पादन-उपरिभारः न्यूनीकरोति ।
समन्वयन-तालाः अतीव कार्यक्षमताग्राहकाः भवन्ति, अतः यदा संकलकः कश्चन वस्तु न पलायितः इति निर्धारयति तदा सः समन्वयन-तालान् वस्तुतः निष्कासयिष्यति । JDK1.8 पूर्वनिर्धारितरूपेण समन्वयनतालानि सक्षमं करोति, परन्तु एतत् पलायनविश्लेषणं सक्षमीकरणे आधारितम् अस्ति ।
- -XX:+EliminateLocks #开启同步锁消除(JVM默认状态)
- -XX:-EliminateLocks #关闭同步锁消除
- 通过示例: 明显可以看到“逃逸分析和锁消除” 对性能的提升
-
- public void testLock(){
- long t1 = System.currentTimeMillis();
- for (int i = 0; i < 100_000_000; i++) {
- locketMethod();
- }
- long t2 = System.currentTimeMillis();
- System.out.println("耗时:"+(t2-t1));
- }
-
- public static void locketMethod(){
- EscapeAnalysis escapeAnalysis = new EscapeAnalysis();
- synchronized(escapeAnalysis) {
- escapeAnalysis.obj2="abcdefg";
- }
- }
-
- 设置JVM参数,开启逃逸分析, 耗时:
- java -Xmx64m -Xms64m -XX:+DoEscapeAnalysis
-
- 设置JVM参数,关闭逃逸分析, 耗时:
- java -Xmx64m -Xms64m -XX:-DoEscapeAnalysis
-
- 设置JVM参数,关闭锁消除,再次运行
- java -Xmx64m -Xms15m -XX:+DoEscapeAnalysis -XX:-EliminateLocks
-
- 设置JVM参数,开启锁消除,再次运行
- java -Xmx64m -Xms15m -XX:+DoEscapeAnalysis -XX:+EliminateLocks
-
-
सूत्रसमन्वयनस्य व्ययः अत्यन्तं अधिकः भवति, समन्वयनस्य परिणामः च समवर्तीता, कार्यक्षमता च न्यूनीभवति ।
समन्वयितखण्डस्य गतिशीलरूपेण संकलनं कुर्वन् JIT संकलकः पलायनविश्लेषणस्य उपयोगं कृत्वा निर्धारयितुं शक्नोति यत् समन्वयितखण्डेन प्रयुक्तं तालावस्तु केवलं एकेन सूत्रेण एव अभिगन्तुं शक्यते अन्येभ्यः सूत्रेभ्यः न मुक्तं वा इति यदि न, तर्हि JIT संकलकः अस्य समन्वयितखण्डस्य संकलनकाले कोडस्य एतत् भागं विसमन्वयनं करिष्यति । एतेन समवर्तीतायां कार्यप्रदर्शने च महती उन्नतिः भवितुम् अर्हति । समन्वयनस्य रद्दीकरणस्य एषा प्रक्रिया समन्वयनलोपः इति कथ्यते, यत् तालानिराकरणम् अपि कथ्यते ।
- 例如下面的代码
-
- public void f() {
- Object hellis = new Object();
- synchronized(hellis) {
- System.out.println(hellis);
- }
- }
- 代码中对hellis这个对象加锁,但是hellis对象的生命周期只在f()方法中,并不会被其他线程所访问到,所以在JIT编译阶段就会被优化掉,优化成:
-
- public void f() {
- Object hellis = new Object();
- System.out.println(hellis);
- }
- 我们将其转换成字节码,此处发现,还是有同步锁的身影,是因为优化是在编译阶段的,在加载进内存后发生。
पलायनविश्लेषणं वस्तुं बहुषु स्केलरेषु, यथा आदिमप्रकारेषु अन्येषु वा वस्तुषु विभज्य, तान् भिन्नस्थानेषु नियुक्तुं शक्नोति । एतेन स्मृतिविखण्डनं वस्तुप्रवेशस्य उपरितनं च न्यूनीकर्तुं शक्यते, स्मृतिप्रयोगदक्षतां च सुदृढं कर्तुं शक्यते ।
सर्वप्रथमं अस्माभिः स्केलर्स्, एग्रीगेट् च अवगन्तुं शक्यते मूलभूतप्रकारस्य वस्तुनां च सन्दर्भाः स्केलर इति अवगन्तुं शक्यन्ते, ते च अधिकं विघटितुं न शक्यन्ते । यत् परिमाणं अधिकं विघटितुं शक्यते तत् समुच्चयमात्रा यथा : वस्तु ।
वस्तु एकः समुच्चयः परिमाणः अस्ति, यस्य विघटनं अधिकं स्केलररूपेण कर्तुं शक्यते तथा च तस्य सदस्यचराः विच्छिन्नचररूपेण कर्तुं शक्यन्ते एतत् स्केलरप्रतिस्थापनम् इति कथ्यते ।
एवं प्रकारेण यदि कश्चन वस्तु न पलायते तर्हि तस्य निर्माणस्य सर्वथा आवश्यकता नास्ति केवलं तया उपयुज्यमानाः सदस्यस्केलराः एव स्टैक् अथवा रजिस्टर् इत्यत्र निर्मिताः भविष्यन्ति, येन स्मृतिस्थानं रक्षति तथा च अनुप्रयोगस्य कार्यक्षमतां सुधरति
JDK1.8 इत्यस्मिन् पूर्वनिर्धारितरूपेण स्केलर प्रतिस्थापनम् अपि सक्षमम् अस्ति, परन्तु तत् सक्षमीकरणस्य पलायनविश्लेषणस्य आधारेण अपि भवितुमर्हति ।
स्केलर इति एकः दत्तांशः यः लघुदत्तांशेषु विभक्तुं न शक्यते । जावा मध्ये आदिमः दत्तांशप्रकारः स्केलरः अस्ति ।
तस्य विपरीतम्, यत् दत्तांशं विघटितुं शक्यते, तत् समुच्चयम् इति उच्यते, यतः तत् अन्येषु समुच्चयेषु, स्केलरेषु च विघटितुं शक्यते ।
- public static void main(String args[]) {
- alloc();
- }
- class Point {
- private int x;
- private int y;
- }
- private static void alloc() {
- Point point = new Point(1,2);
- System.out.println("point.x" + point.x + ";point.y" + point.y);
- }
- 以上代码,经过标量替换后,就会变成
-
- private static void alloc() {
- int x = 1;
- int y = 2;
- System.out.println("point.x = " + x + "; point.y=" + y);
- }
JIT चरणे यदि पलायनविश्लेषणद्वारा ज्ञायते यत् कश्चन वस्तु बहिः जगत् न अभिगमिष्यति, तर्हि JIT अनुकूलनस्य अनन्तरं वस्तु तस्मिन् निहितानाम् अनेकसदस्यचरानाम् विच्छेदनं कृत्वा प्रतिस्थापितं भविष्यति एषा प्रक्रिया स्केलर प्रतिस्थापनम् अस्ति ।
द्रष्टुं शक्यते यत् पलायनविश्लेषणानन्तरं समुच्चयमात्रा Point इति न पलायितः इति ज्ञातम् अतः तस्य स्थाने द्वौ स्केलरौ स्थापितः । अतः अङ्कीयप्रतिस्थापनस्य के लाभाः सन्ति ? अर्थात्, एतेन ढेरस्मृतिप्रयोगं बहु न्यूनीकर्तुं शक्यते । यतः एकदा वस्तुनिर्माणस्य आवश्यकता नास्ति तदा heap memory आवंटनस्य आवश्यकता नास्ति । स्केलर प्रतिस्थापनं स्टैक् इत्यत्र आवंटनस्य उत्तमं आधारं प्रदाति ।
पलायन विश्लेषण परीक्षण
- 逃逸分析测试
- 代码如下,大致思路就是 for 循环 1 亿次,循环体内调用外部的 allot() 方法,而 allot() 方法的作用就是简单创建一个对象,但是这个对象是内部的,所以是未逃逸的,所以理论上 JVM 是会进行优化的,我们拭目以待。并且我们会对比开启和关闭逃逸分析之后各自程序的运行时间:
-
- /**
- * @ClassName: EscapeAnalysisTest
- * @Description: http://www.jetchen.cn 逃逸分析 demo
- * @Author: Jet.Chen
- * @Date: 2020/11/23 14:26
- * @Version: 1.0
- **/
- public class EscapeAnalysisTest {
-
- public static void main(String[] args) {
- long t1 = System.currentTimeMillis();
- for (int i = 0; i < 100000000; i++) {
- allot();
- }
- long t2 = System.currentTimeMillis();
- System.out.println(t2-t1);
- }
-
- private static void allot() {
- Jet jet = new Jet();
- }
-
- static class Jet {
- public String name;
- }
-
- }
- 上面就是我们进行逃逸分析测试的代码, mian() 方法末尾有一个线程暂停,目的是为了观察此时 JVM 中的内存情况。
-
- Step 1:测试开启逃逸
- 由于环境是 jdk1.8,默认开启了逃逸分析,所以直接运行,得到结果如下,程序耗时 3 毫秒:
-
-
- 此时线程是处于睡眠状态的,我们观察下内存情况,发现堆内存中一共新建了 11 万个 Jet 对象。
-
-
-
- Step 2:测试关闭逃逸
- 我们关闭逃逸分析再来运行一次(使用 java -XX:-DoEscapeAnalysis EscapeAnalysisTest 来运行代码即可),得到结果如下,程序耗时 400 毫秒:
-
-
- 此时我们观察下内存情况,发现堆内存中一共新建了 3 千多万个 Jet 对象。
-
-
- 所以,无论是从代码的执行时间(3 毫秒 VS 400 毫秒),还是从堆内存中对象的数量(11 万个 VS 3 千万个)来分析,在上述场景下,开启逃逸分析是有正向益的。
-
- Step 3:测试标量替换
- 我们测试下开启和关闭 标量替换,如下图:
-
-
- 由上图我们可以看出,在上述极端场景下,开启和关闭标量替换对于性能的影响也是满巨大的,另外,同时也验证了标量替换功能生效的前提是逃逸分析已经开启,否则没有意义。
-
- Step 4:测试锁消除
- 测试锁消除,我们需要简单调整下代码,即给 allot() 方法中的内容加锁处理,如下:
-
- private static void allot() {
- Jet jet = new Jet();
- synchronized (jet) {
- jet.name = "jet Chen";
- }
- }
- 然后我们运行测试代码,测试结果也很明显,在上述场景下,开启和关闭锁消除对程序性能的影响也是巨大的。
-
-
- /**
- * 进行两种测试
- * 关闭逃逸分析,同时调大堆空间,避免堆内GC的发生,如果有GC信息将会被打印出来
- * VM运行参数:-Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
- *
- * 开启逃逸分析 jdk8默认开启
- * VM运行参数:-Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
- *
- * 执行main方法后
- * jps 查看进程
- * jmap -histo 进程ID
- *
- */
- @Slf4j
- public class EscapeTest {
-
- public static void main(String[] args) {
- long start = System.currentTimeMillis();
- for (int i = 0; i < 500000; i++) {
- alloc();
- }
- long end = System.currentTimeMillis();
- log.info("执行时间:" + (end - start) + " ms");
- try {
- Thread.sleep(Integer.MAX_VALUE);
- } catch (InterruptedException e1) {
- e1.printStackTrace();
- }
- }
-
-
- /**
- * JIT编译时会对代码进行逃逸分析
- * 并不是所有对象存放在堆区,有的一部分存在线程栈空间
- * Ponit没有逃逸
- */
- private static String alloc() {
- Point point = new Point();
- return point.toString();
- }
-
- /**
- *同步省略(锁消除) JIT编译阶段优化,JIT经过逃逸分析之后发现无线程安全问题,就会做锁消除
- */
- public void append(String str1, String str2) {
- StringBuffer stringBuffer = new StringBuffer();
- stringBuffer.append(str1).append(str2);
- }
-
- /**
- * 标量替换
- *
- */
- private static void test2() {
- Point point = new Point(1,2);
- System.out.println("point.x="+point.getX()+"; point.y="+point.getY());
-
- // int x=1;
- // int y=2;
- // System.out.println("point.x="+x+"; point.y="+y);
- }
-
-
- }
-
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- class Point{
- private int x;
- private int y;
- }
पलायनविश्लेषणेन निर्धारयितुं शक्यते यत् केचन विधि-आह्वानाः वर्तमान-विधेः व्याप्तेः पलायनं न करिष्यन्ति । अतः एतानि मेथड्स् इन्लाइन् अनुकूलितं कर्तुं शक्यन्ते येन मेथड् कॉल् इत्यस्य व्ययः न्यूनीकर्तुं शक्यते तथा च प्रोग्रामस्य एक्जीक्यूटिव् दक्षतायां सुधारः भवति ।
एतेषां अनुकूलनरणनीतीनां माध्यमेन पलायनविश्लेषणं JVM इत्यस्य कोडस्य उत्तमरीत्या अनुकूलनं कर्तुं, कचरासंग्रहणस्य उपरितनं न्यूनीकर्तुं, कार्यक्रमनिष्पादनदक्षतां प्रतिक्रियाशीलतां च सुधारयितुम्, स्मृतिप्रयोगं न्यूनीकर्तुं च सहायं कर्तुं शक्नोति
पलायनविश्लेषणस्य वास्तविकजावा अनुप्रयोगेषु अनुप्रयोगपरिदृश्यानां विस्तृतश्रेणी भवति निम्नलिखितम् केचन सामान्याः अनुप्रयोगपरिदृश्याः सन्ति ।
पलायनविश्लेषणविषये पत्रं १९९९ तमे वर्षे प्रकाशितम्, परन्तु JDK1.6 पर्यन्तं तत् कार्यान्वितं न जातम्, एषा प्रौद्योगिकी अद्यापि बहु परिपक्वा नास्ति ।
मौलिकं कारणं यत् पलायनविश्लेषणस्य कार्यप्रदर्शनस्य उपभोगः तस्य उपभोगात् अधिकः भविष्यति इति गारण्टी नास्ति । यद्यपि पलायनविश्लेषणं स्केलरप्रतिस्थापनं, स्टैक् आवंटनं, तालनिराकरणं च कर्तुं शक्नोति । परन्तु पलायनविश्लेषणे एव जटिलविश्लेषणस्य श्रृङ्खलायाः अपि आवश्यकता भवति, या वस्तुतः तुल्यकालिकरूपेण समयग्राही प्रक्रिया अस्ति ।
अत्यन्तं उदाहरणं यत् पलायनविश्लेषणानन्तरं कोऽपि वस्तु न पलायते इति ज्ञायते । ततः पलायनविश्लेषणप्रक्रिया अपव्ययः भवति।
यद्यपि एषा प्रौद्योगिकी अतीव परिपक्वा नास्ति तथापि जस्ट्-इन्-टाइम-कम्पाइलर-अनुकूलन-प्रौद्योगिक्यां अपि अतीव महत्त्वपूर्णं साधनम् अस्ति । मया अवलोकितं यत् केचन मताः सन्ति यत् पलायनविश्लेषणस्य माध्यमेन JVM स्तम्भे तादृशानि वस्तुनि आवंटयिष्यति ये पलायनं न करिष्यन्ति एतत् सैद्धान्तिकरूपेण सम्भवम्, परन्तु एतत् JvM डिजाइनरस्य चयनस्य उपरि निर्भरं भवति । यावत् अहं जानामि, Oracle Hotspot JVM एतत् न करोति, एतत् escape analysis सम्बद्धेषु दस्तावेजेषु व्याख्यातं अस्ति, अतः स्पष्टं यत् सर्वे object instances heap इत्यत्र निर्मिताः सन्ति ।
वर्तमान समये JDK7 इत्यस्य पूर्वं संस्करणानाम् आधारेण बहवः पुस्तकानि महतीनि परिवर्तनानि अभवन् । तथापि, intern string cache तथा static variables मेटाडाटा क्षेत्रे स्थानान्तरिताः न भवन्ति, परन्तु प्रत्यक्षतया heap इत्यत्र आवंटिताः भवन्ति, अतः एतत् पूर्वबिन्दुस्य निष्कर्षेण सह अपि सङ्गतम् अस्ति: object instances heap इत्यत्र आवंटिताः भवन्ति उपरिष्टाद् उदाहरणं स्केलर-प्रतिस्थापनस्य कारणेन त्वरितम् अस्ति ।
यदि कश्चन वस्तु विधिशरीरस्य अन्तः वा सूत्रस्य अन्तः वा न पलायते (अथवा पलायनविश्लेषणानन्तरं पलायितुं असफलः इति निर्धारितं भवति), तर्हि निम्नलिखित अनुकूलनं कर्तुं शक्यते ।
सामान्यपरिस्थितौ ये वस्तूनि पलायितुं न शक्नुवन्ति ते तुल्यकालिकरूपेण विशालं स्थानं गृह्णन्ति यदि स्तम्भे स्थानं उपयोक्तुं शक्यते तर्हि विधिः समाप्तः भवति तदा बहूनां वस्तूनि नष्टानि भविष्यन्ति, येन जीसी-दाबः न्यूनीकरोति
यदि भवता परिभाषितस्य वर्गस्य विधिः समन्वयन-ताला अस्ति, परन्तु केवलं एकः सूत्रः रनटाइम्-समये तत् अभिगच्छति, तर्हि पलायन-विश्लेषणानन्तरं यन्त्र-सङ्केतः समन्वयन-तालं विना चालयिष्यति
जावा वर्चुअल् मशीन् इत्यस्मिन् आदिमदत्तांशप्रकाराः (int, long, सन्दर्भप्रकाराः इत्यादयः संख्यात्मकाः प्रकाराः) अधिकं विघटितुं न शक्यन्ते, ते च स्केलर इति वक्तुं शक्यन्ते तदपेक्षया यदि दत्तांशस्य कश्चन भागः निरन्तरं विघटितः भवितुम् अर्हति तर्हि सः समुच्चयः इति कथ्यते । यदि पलायनविश्लेषणेन सिद्धं भवति यत् कश्चन वस्तु बाह्यरूपेण न अभिगम्यते तथा च वस्तु विघटनीयः अस्ति तर्हि वस्तुनः निर्माणं न भवेत् यदा कार्यक्रमः वास्तविकरूपेण निष्पादितः भवति, अपितु तस्य स्थाने प्रत्यक्षतया अस्य पद्धत्या प्रतिस्थापनार्थं प्रयुक्तानां सदस्यचरानाम् अनेकानाम् निर्माणं भवति विच्छेदितचरानाम् पृथक् पृथक् विश्लेषणं अनुकूलितं च कर्तुं शक्यते, सन्दर्भसूचकानाम् माध्यमेन सम्बन्धस्थापनस्य आवश्यकता नास्ति, यत् विभिन्नभण्डारणानां कृते अधिकं मैत्रीपूर्णं भवति तथा च समये बहु दत्तांशनियन्त्रणस्य रक्षणं करोति निष्पादनम् । तस्मिन् एव काले, भवान् क्रमशः stack frame अथवा register इत्यत्र स्थानं आवंटयितुं अपि शक्नोति, येन मूलवस्तुनः समग्ररूपेण स्थानं आवंटयितुं आवश्यकता नास्ति ।
युवानः पीढी इति क्षेत्रं यत्र वस्तुनः जायन्ते, वर्धन्ते, म्रियन्ते च ।
पुरातनपीढीयां स्थापिताः दीर्घायुषः वस्तूनि प्रायः जीवितक्षेत्रात् प्रतिलिपिताः जावावस्तूनि भवन्ति । अवश्यं, विशेषाः प्रकरणाः अपि सन्ति वयं जानीमः यत् TLAB इत्यत्र साधारणवस्तूनि आवंटितानि भविष्यन्ति यदि वस्तु बृहत् अस्ति तर्हि JVM प्रत्यक्षतया एडेन् मध्ये अन्यस्थानेषु आवंटयितुं प्रयतते यदि वस्तु अतीव विशाला अस्ति नूतनपीढीयां पर्याप्तं दीर्घकालं निरन्तरं मुक्तस्थानं अन्वेष्टुं समर्थः भवेत्, JVM प्रत्यक्षतया पुरातनपीढीं प्रति आवंटयिष्यति । यदा GC केवलं युवानां पीढौ भवति तदा युवानां वस्तूनाम् पुनःप्रयोगस्य क्रिया MinorGc इति कथ्यते ।
यदा पुरातनपीढौ GC भवति तदा MajorGc अथवा FullGC इति उच्यते । सामान्यतया MinorGc इत्यस्य आवृत्तिः MajorGC इत्यस्य अपेक्षया बहु अधिका भवति अर्थात् पुरातनपीढीयां कचरासंग्रहणस्य आवृत्तिः युवानां पीढीयाः अपेक्षया बहु न्यूना भविष्यति
JVM escape analysis इत्यनेन स्थिरं गतिशीलं च विश्लेषणविधिद्वयं उपयुज्यते यत् एतत् निर्धारयितुं शक्यते यत् कोऽपि वस्तु विधिस्य व्याप्तेः पलायनं कर्तुं शक्नोति वा इति । इदं JVM इत्यस्य कोडस्य अनुकूलनं कर्तुं तथा च Java प्रोग्राम् इत्यस्य कार्यक्षमतां स्मृतिप्रयोगदक्षतां च सुधारयितुं साहाय्यं कर्तुं शक्नोति ।
पलायनविश्लेषणस्य अनुकूलनरणनीतिषु ऑन-स्टैक् आवंटनं, समन्वयननिराकरणं, स्केलरप्रतिस्थापनं, विधि-इन्लाइनिंग् च सन्ति । एतानि अनुकूलनरणनीतयः कचरासंग्रहणस्य उपरिभारं न्यूनीकर्तुं, कार्यक्रमनिष्पादनदक्षतां प्रतिक्रियाशीलतां च सुधारयितुम्, स्मृतिप्रयोगं न्यूनीकर्तुं च शक्नुवन्ति ।
refer to : १.
https://zhuanlan.zhihu.com/p/693382698
JVM-ढेर-पलायन विश्लेषण-08-CSDN ब्लॉग
JIT स्मृतिपलायन analysis_java अङ्कीयप्रतिस्थापनं-CSDN ब्लॉगं निष्क्रियं करोति
java -XX:+PrintFlagsFinal #输出打印所有参数jvm参数