2009-04-21 20 views
35

में विश्लेषण से बचें जहां तक ​​मुझे पता है कि JVM कुछ प्रदर्शन optimisations जैसे लॉक कोर्सेनिंग और लॉक एलिजन के लिए एस्केप विश्लेषण का उपयोग करता है। मुझे दिलचस्पी है कि JVM के लिए यह निर्णय लेने की संभावना है कि किसी भी विशेष वस्तु को बचने के विश्लेषण का उपयोग करके ढेर पर आवंटित किया जा सकता है।जावा

कुछ resources मुझे लगता है कि मैं सही हूं। क्या वहां जेवीएम हैं जो वास्तव में करते हैं?

+3

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

+0

@anstarovoyt यह गैर-ग्लोबल एस्केपिंग ऑब्जेक्ट्स के लिए एक स्टैक आवंटन के साथ एक ढेर आवंटन को प्रतिस्थापित नहीं करता है। – Aliaxander

+0

@ एलियाक्सेंडर 200 9 में सवाल पूछा गया था और मेरा जवाब 2013 में था :) – anstarovoyt

उत्तर

5

मुझे नहीं लगता कि यह स्टैक आवंटन के लिए विश्लेषण से बच निकलता है। उदाहरण:

public class EscapeAnalysis { 

    private static class Foo { 
     private int x; 
     private static int counter; 

     public Foo() { 
      x = (++counter); 
     } 
    } 
    public static void main(String[] args) { 
     System.out.println("start"); 
     for (int i = 0; i < 10000000; ++i) { 
      Foo foo = new Foo(); 
     } 

     System.out.println(Foo.counter); 
    } 
} 

-server -verbose:gc -XX+DoEscapeAnalysis साथ:

 
start 
[GC 3072K->285K(32640K), 0.0065187 secs] 
[GC 3357K->285K(35712K), 0.0053043 secs] 
[GC 6429K->301K(35712K), 0.0030797 secs] 
[GC 6445K->285K(41856K), 0.0033648 secs] 
[GC 12573K->285K(41856K), 0.0050432 secs] 
[GC 12573K->301K(53952K), 0.0043682 secs] 
[GC 24877K->277K(53952K), 0.0031890 secs] 
[GC 24853K->277K(78528K), 0.0005293 secs] 
[GC 49365K->277K(78592K), 0.0006699 secs] 
10000000 

कथित तौर पर JDK 7 supports stack allocation

+0

जावा 7 में दस्तावेज़ों के लिए लिंक यहां दिया गया है: http: // docs।oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis – robinst

+1

मुझे लगता है कि आप wrong.you न यहाँ एक वार्मअप चरण होते हैं। इस पोस्ट को देख - https://minborgsjavapot.blogspot.co.il/2015/12/do-not-let-your-java-objects-escape.html –

90

जावा -XX के इस संस्करण के साथ: + DoEscapeAnalysis के परिणामस्वरूप बहुत कम जीसी गतिविधि और 14x तेज निष्पादन होता है।

$ java -version 
java version "1.6.0_14" 
Java(TM) SE Runtime Environment (build 1.6.0_14-b08) 
    Java HotSpot(TM) Client VM (build 14.0-b16, mixed mode, sharing) 

$ uname -a 
Linux xxx 2.6.18-4-686 #1 SMP Mon Mar 26 17:17:36 UTC 2007 i686 GNU/Linux 
भागने विश्लेषण के बिना

,

$ java -server -verbose:gc EscapeAnalysis|cat -n 
    1 start 
    2 [GC 896K->102K(5056K), 0.0053480 secs] 
    3 [GC 998K->102K(5056K), 0.0012930 secs] 
    4 [GC 998K->102K(5056K), 0.0006930 secs] 
    --snip-- 
    174 [GC 998K->102K(5056K), 0.0001960 secs] 
    175 [GC 998K->102K(5056K), 0.0002150 secs] 
    176 10000000 
भागने विश्लेषण के साथ

,

$ java -server -verbose:gc -XX:+DoEscapeAnalysis EscapeAnalysis 
start 
[GC 896K->102K(5056K), 0.0055600 secs] 
10000000 

निष्पादन समय बच विश्लेषण के साथ काफी कम कर देता है। इसके लिए पाश 10e9 पुनरावृत्तियों में बदल गया था,

public static void main(String [] args){ 
    System.out.println("start"); 
    for(int i = 0; i < 1000*1000*1000; ++i){ 
     Foo foo = new Foo(); 
    } 
    System.out.println(Foo.counter); 
} 

भागने विश्लेषण के बिना,

$ time java -server EscapeAnalysis 
start 
1000000000 

real 0m27.386s 
user 0m24.950s 
sys  0m1.076s 
भागने विश्लेषण के साथ

,

$ time java -server -XX:+DoEscapeAnalysis EscapeAnalysis 
start 
1000000000 

real 0m2.018s 
user 0m2.004s 
sys  0m0.012s 

तो बच विश्लेषण के साथ उदाहरण के भाग की तुलना में के बारे में 14 गुना तेजी से गैर-भागने का विश्लेषण चलाएं।

+2

आप "जावा -server" तो आप का उपयोग करना चाहिए चलाते हैं "जावा -सर्वर -वर्जन "अपने संस्करण को देखने के लिए, न सिर्फ" जावा-वर्जन "। – Oak

+13

यह बहुत अच्छा काम करता है। स्वीकार किए जाते हैं जवाब – HRJ

+1

भी देखें इसके बारे में जावा 7 प्रलेखन होना चाहिए: http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis – robinst

2

एस्केप विश्लेषण वास्तव में अच्छा है, लेकिन यह जेल फ्री कार्ड का पूरा पूरा नहीं है। यदि आपके पास किसी ऑब्जेक्ट के अंदर गतिशील रूप से आकार का संग्रह है, तो बचने का विश्लेषण ढेर से ढेर तक नहीं स्विच होगा। उदाहरण के लिए:

public class toEscape { 
    public long l; 
    public List<Long> longList = new ArrayList<Long>(); 
} 

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

+0

ऐसा इसलिए है क्योंकि 'लांगलिस्ट' को 'toEscape के कन्स्ट्रक्टर में आवंटित किया गया है। कन्स्ट्रक्टर को रेखांकित नहीं किया जाता है, इसलिए 'लांगलिस्ट' संदर्भ इसलिए बच निकलता है। इस मामले में वस्तु का प्रकार कोई फर्क नहीं पड़ता। –