İstisna atmanın hangi kısmı pahalıdır?


256

Java'da, aslında bir hata olmadığında fırlatma / yakalama mantığın bir parçası olarak kullanmak genellikle kötü bir fikirdir (kısmen), çünkü bir istisnayı atmak ve yakalamak pahalıdır ve bunu bir döngüde birçok kez yapmak genellikle diğerlerinden çok daha yavaştır istisnalar atmayı içermeyen kontrol yapıları.

Benim sorum, atma / yakalamada ya da Exception nesnesini oluştururken ortaya çıkan maliyet (yürütme yığını da dahil olmak üzere çok sayıda çalışma zamanı bilgisi aldığı için)?

Başka bir deyişle, eğer

Exception e = new Exception();

ama atmayın, bu fırlatma maliyetinin büyük bir kısmı mıdır, yoksa fırlatma + yakalama da pahalı olanı ele alıyor mu?

Bir try / catch bloğuna kod koyarak bu kodu yürütmenin maliyetini ekleyip eklemediğini sormuyorum, İstisna'yı yakalamanın pahalı kısım olup olmadığını veya (yapıcıyı çağırmak için) İstisna pahalı kısım olup olmadığını soruyorum .

Bunu sormanın bir başka yolu, bir İstisna örneği oluşturup tekrar tekrar atarsam, her attığımda yeni bir İstisna yaratmaktan çok daha hızlı olur mu?


20
Yığın izini doldurup doldurduğuna inanıyorum.
Elliott Frisch

12
Jorge

"Bir İstisna örneği oluşturup attı ve tekrar tekrar yakalarsam," İstisna oluşturulduğunda yığın izlemesi doldurulur, bu da atıldığı yerden bağımsız olarak her zaman aynı stattrace olacağı anlamına gelir. Stacktrace sizin için önemli değilse, fikrinizi deneyebilirsiniz, ancak bu bazı durumlarda hata ayıklamayı çok zor hale getirebilir.
Pshemo

2
@Pshemo Aslında bunu kodda yapmayı planlamıyorum , ben performans hakkında soruyorum ve bu saçmalık fark yaratabilir bir örnek olarak kullanarak.
Martin Carney

@MartinCarney Son paragrafınıza bir yanıt ekledim, yani bir İstisna önbelleğe almanın performans kazancı olur. Yararlıysa, kodu ekleyebilirim, değilse cevabı silebilirim.
Harry

Yanıtlar:


267

Yaratmak bir istisna nesnesi diğer normal nesneleri oluştururken daha pahalı değildir. Ana maliyet, fillInStackTraceçağrı yığını içinde yürüyen ve bir yığın izlemesi oluşturmak için gerekli tüm bilgileri toplayan yerel yöntemde gizlenir : sınıflar, yöntem adları, satır numaraları vb.

Yüksek istisna maliyetleri hakkındaki efsane, Throwableinşaatçıların çoğunun dolaylı olarak çağırdığı gerçeğinden kaynaklanmaktadır fillInStackTrace. Bununla birlikte, bir tane olan yapıcı bir oluşturmak için Throwablebir yığın iz bırakmadan. Anlaşılması çok hızlı olan sarf malzemeleri yapmanıza izin verir. Hafif istisnalar oluşturmanın başka bir yolu da geçersiz kılmaktır fillInStackTrace.


Şimdi bir istisna atmaya ne dersiniz ?
Aslında, atılan bir istisnanın nerede yakalandığına bağlıdır .

Aynı yöntemde (veya daha doğrusu, aynı bağlamda, bağlam satır içi işlemden dolayı çeşitli yöntemler içerebileceğinden) yakalanırsa, (elbette JIT derlemesinden sonra) throwkadar hızlı ve basittir goto.

Bununla birlikte, bir catchblok yığının daha derin bir yerinde ise, JVM'nin yığın çerçevelerini çözmesi gerekir ve bu önemli ölçüde daha uzun sürebilir. synchronizedİlgili bloklar veya yöntemler varsa daha da uzun sürer , çünkü çözme kaldırılan yığın çerçevelerine ait monitörlerin serbest bırakılmasını gerektirir.


Yukarıdaki ifadeleri uygun kriterler ile doğrulayabilirim, ancak neyse ki bunu yapmam gerekmiyor, çünkü tüm yönler HotSpot'un performans mühendisi Alexey Shipilev: Lil'in İstisnai Performansı'nın postunda zaten mükemmel bir şekilde kapsanıyor .


8
Makalede belirtildiği ve burada değinilen sonuç, istisnaları atma / yakalama maliyetinin büyük ölçüde çağrıların derinliğine bağlı olmasıdır. Buradaki nokta, "istisnalar pahalıdır" ifadesinin doğru olmadığıdır. Daha doğru bir ifade 'istisnaların' pahalı olabileceğidir. Dürüst olmak gerekirse, sadece "gerçekten istisnai durumlar" (makalede olduğu gibi) için istisnalar kullanmanın çok güçlü bir şekilde ifade edildiğini düşünüyorum. Normal dönüş akışı dışındaki hemen hemen her şey için mükemmeldir ve gerçek bir uygulamada bu şekilde kullanmanın performans etkisini tespit etmek zordur.
JimmyJames

14
İstisnaların yükünü ölçmek buna değebilir. Bu oldukça kapsamlı makalede bildirilen en kötü durumda bile (aslında sorgulanan bir yığın iziyle dinamik bir istisna atma ve yakalama, 1000 yığın kare derinlik) 80 mikro saniye sürer. Sisteminizin saniyede binlerce istisnayı işlemesi gerekiyorsa bu önemli olabilir, ancak aksi halde endişelenmeye değmez. Ve bu en kötü durum; yığın izlemeleriniz biraz daha akılcıysa veya yığın izlemesini sorgulamazsanız, saniyede yaklaşık bir milyon istisna işleyebiliriz.
Meriton

13
Bunu vurguluyorum çünkü birçok kişi, istisnaların "pahalı" olduğunu okuduktan sonra, "neye kıyasla pahalı" diye sormayı asla bırakmaz, ama çok nadiren "programlarının pahalı kısmı" olduklarını varsayarlar.
Meriton

2
Burada belirtilmeyen bir kısım vardır: optimizasyonların uygulanmasını önlemedeki potansiyel maliyet. Aşırı bir örnek JVM "çamurluk" yığın izleri önlemek için inlining olurdu, ama istisnaların varlığı veya yokluğu C ++ daha önce optimizasyon yapacak veya kırmak nerede (mikro) kriterler gördüm.
Matthieu M.

3
@MatthieuM. İstisnalar ve try / catch blokları JVM'nin satır içine girmesini engellemez. Derlenmiş yöntemler için gerçek yığın izleri, meta veri olarak depolanan sanal yığın çerçeve tablosundan yeniden oluşturulur. Try / catch ile uyumlu olmayan bir JIT optimizasyonunu hatırlayamıyorum. Try / catch yapısının kendisi yöntem koduna hiçbir şey eklemez, sadece kodun dışında bir istisna tablosu olarak bulunur.
apangin

72

Çoğu Throwablekurucudaki ilk işlem , giderin çoğunun bulunduğu yığın izini doldurmaktır .

Bununla birlikte, yığın izlemesini devre dışı bırakmak için bayrağı olan korumalı bir kurucu vardır. Bu kurucuya genişletirken Exceptionde erişilebilir . Özel bir istisna türü oluşturursanız, yığın izlemesi oluşturmayı önleyebilir ve daha az bilgi pahasına daha iyi performans elde edebilirsiniz.

Normal yollarla herhangi bir türden tek bir istisna oluşturursanız, yığın izini doldurma yükü olmadan birçok kez yeniden atabilirsiniz. Bununla birlikte, yığın izlemesi, belirli bir durumda atıldığı yeri değil, inşa edildiği yeri yansıtacaktır.

Java'nın şu anki sürümleri yığın izleme oluşturmayı optimize etmek için bazı girişimlerde bulunur. Yerel kod, izi daha hafif, yerel bir yapıda kaydeden yığın izini doldurması için çağrılır. Sorumlu Java StackTraceElementnesneleri tembel yalnızca bu kayıttan oluşturulur getStackTrace(), printStackTrace()iz gerektiren veya diğer yöntemler olarak adlandırılır.

Yığın izleme üretimini ortadan kaldırırsanız, diğer ana maliyet, yığını atış ve yakalama arasındaki yığını çözmektir. İstisna yakalanmadan önce ne kadar az müdahale eden kareyle karşılaşılırsa, o kadar hızlı olur.

Programınızı yalnızca istisnai durumlarda istisnalar atılacak şekilde tasarlayın ve bunun gibi optimizasyonların haklı çıkarılması zor.



25

Burada İstisnalar hakkında iyi bir yazı var.

http://shipilev.net/blog/2014/exceptional-performance/

Sonuç olarak yığın iz yapısı ve yığın çözme pahalı kısımlardır. Aşağıdaki kod 1.7, yığın izlerini açıp kapatabildiğimiz bir özellikten yararlanır . Daha sonra bunu farklı senaryoların ne tür maliyetlere sahip olduğunu görmek için kullanabiliriz

Aşağıdakiler yalnızca Nesne oluşturma zamanlamalarıdır. Buraya ekledim, Stringböylece yığın yazılmadan bir JavaExceptionNesne ve a oluşturmada neredeyse hiçbir fark yoktur String. Yığın yazma açıkken, fark dramatiktir, yani en az bir büyüklük sırası daha yavaştır.

Time to create million String objects: 41.41 (ms)
Time to create million JavaException objects with    stack: 608.89 (ms)
Time to create million JavaException objects without stack: 43.50 (ms)

Aşağıda, belirli bir derinlikte atıştan milyonlarca kez dönmenin ne kadar sürdüğü gösterilmektedir.

|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%)|
|   16|           1428|             243| 588 (%)|
|   15|           1763|             393| 449 (%)|
|   14|           1746|             390| 448 (%)|
|   13|           1703|             384| 443 (%)|
|   12|           1697|             391| 434 (%)|
|   11|           1707|             410| 416 (%)|
|   10|           1226|             197| 622 (%)|
|    9|           1242|             206| 603 (%)|
|    8|           1251|             207| 604 (%)|
|    7|           1213|             208| 583 (%)|
|    6|           1164|             206| 565 (%)|
|    5|           1134|             205| 553 (%)|
|    4|           1106|             203| 545 (%)|
|    3|           1043|             192| 543 (%)| 

Aşağıdakiler neredeyse kesinlikle sadeleştirme üzerinden bir brüttür ...

Yığın yazma özelliği ile 16 derinliği alırsak, nesne oluşturma sürenin yaklaşık% ~ 40'ını alırsa, gerçek yığın izlemesi bunun büyük çoğunluğunu oluşturur. JavaException nesnesinin örneğinin ~% 93'ünün yığın izinin alınması nedeniyle. Bu, bu durumda destenin çözülmesinin zamanın diğer% 50'sini aldığı anlamına gelir.

Yığın izleme nesnesi oluşturma işlemi kapatıldığında, çok daha küçük bir kesir, yani% 20 ve yığın çözme, zamanın% 80'ini oluşturur.

Her iki durumda da yığın çözme işlemi toplam sürenin büyük bir kısmını alır.

public class JavaException extends Exception {
  JavaException(String reason, int mode) {
    super(reason, null, false, false);
  }
  JavaException(String reason) {
    super(reason);
  }

  public static void main(String[] args) {
    int iterations = 1000000;
    long create_time_with    = 0;
    long create_time_without = 0;
    long create_string = 0;
    for (int i = 0; i < iterations; i++) {
      long start = System.nanoTime();
      JavaException jex = new JavaException("testing");
      long stop  =  System.nanoTime();
      create_time_with += stop - start;

      start = System.nanoTime();
      JavaException jex2 = new JavaException("testing", 1);
      stop = System.nanoTime();
      create_time_without += stop - start;

      start = System.nanoTime();
      String str = new String("testing");
      stop = System.nanoTime();
      create_string += stop - start;

    }
    double interval_with    = ((double)create_time_with)/1000000;
    double interval_without = ((double)create_time_without)/1000000;
    double interval_string  = ((double)create_string)/1000000;

    System.out.printf("Time to create %d String objects: %.2f (ms)\n", iterations, interval_string);
    System.out.printf("Time to create %d JavaException objects with    stack: %.2f (ms)\n", iterations, interval_with);
    System.out.printf("Time to create %d JavaException objects without stack: %.2f (ms)\n", iterations, interval_without);

    JavaException jex = new JavaException("testing");
    int depth = 14;
    int i = depth;
    double[] with_stack    = new double[20];
    double[] without_stack = new double[20];

    for(; i > 0 ; --i) {
      without_stack[i] = jex.timerLoop(i, iterations, 0)/1000000;
      with_stack[i]    = jex.timerLoop(i, iterations, 1)/1000000;
    }
    i = depth;
    System.out.printf("|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%%)|\n");
    for(; i > 0 ; --i) {
      double ratio = (with_stack[i] / (double) without_stack[i]) * 100;
      System.out.printf("|%5d| %14.0f| %15.0f| %2.0f (%%)| \n", i + 2, with_stack[i] , without_stack[i], ratio);
      //System.out.printf("%d\t%.2f (ms)\n", i, ratio);
    }
  }
 private int thrower(int i, int mode) throws JavaException {
    ExArg.time_start[i] = System.nanoTime();
    if(mode == 0) { throw new JavaException("without stack", 1); }
    throw new JavaException("with stack");
  }
  private int catcher1(int i, int mode) throws JavaException{
    return this.stack_of_calls(i, mode);
  }
  private long timerLoop(int depth, int iterations, int mode) {
    for (int i = 0; i < iterations; i++) {
      try {
        this.catcher1(depth, mode);
      } catch (JavaException e) {
        ExArg.time_accum[depth] += (System.nanoTime() - ExArg.time_start[depth]);
      }
    }
    //long stop = System.nanoTime();
    return ExArg.time_accum[depth];
  }

  private int bad_method14(int i, int mode) throws JavaException  {
    if(i > 0) { this.thrower(i, mode); }
    return i;
  }
  private int bad_method13(int i, int mode) throws JavaException  {
    if(i == 13) { this.thrower(i, mode); }
    return bad_method14(i,mode);
  }
  private int bad_method12(int i, int mode) throws JavaException{
    if(i == 12) { this.thrower(i, mode); }
    return bad_method13(i,mode);
  }
  private int bad_method11(int i, int mode) throws JavaException{
    if(i == 11) { this.thrower(i, mode); }
    return bad_method12(i,mode);
  }
  private int bad_method10(int i, int mode) throws JavaException{
    if(i == 10) { this.thrower(i, mode); }
    return bad_method11(i,mode);
  }
  private int bad_method9(int i, int mode) throws JavaException{
    if(i == 9) { this.thrower(i, mode); }
    return bad_method10(i,mode);
  }
  private int bad_method8(int i, int mode) throws JavaException{
    if(i == 8) { this.thrower(i, mode); }
    return bad_method9(i,mode);
  }
  private int bad_method7(int i, int mode) throws JavaException{
    if(i == 7) { this.thrower(i, mode); }
    return bad_method8(i,mode);
  }
  private int bad_method6(int i, int mode) throws JavaException{
    if(i == 6) { this.thrower(i, mode); }
    return bad_method7(i,mode);
  }
  private int bad_method5(int i, int mode) throws JavaException{
    if(i == 5) { this.thrower(i, mode); }
    return bad_method6(i,mode);
  }
  private int bad_method4(int i, int mode) throws JavaException{
    if(i == 4) { this.thrower(i, mode); }
    return bad_method5(i,mode);
  }
  protected int bad_method3(int i, int mode) throws JavaException{
    if(i == 3) { this.thrower(i, mode); }
    return bad_method4(i,mode);
  }
  private int bad_method2(int i, int mode) throws JavaException{
    if(i == 2) { this.thrower(i, mode); }
    return bad_method3(i,mode);
  }
  private int bad_method1(int i, int mode) throws JavaException{
    if(i == 1) { this.thrower(i, mode); }
    return bad_method2(i,mode);
  }
  private int stack_of_calls(int i, int mode) throws JavaException{
    if(i == 0) { this.thrower(i, mode); }
    return bad_method1(i,mode);
  }
}

class ExArg {
  public static long[] time_start;
  public static long[] time_accum;
  static {
     time_start = new long[20];
     time_accum = new long[20];
  };
}

Bu örnekteki yığın kareleri, normalde bulduğunuz şeye kıyasla küçüktür.

Javap kullanarak bayt koduna göz atabilirsiniz

javap -c -v -constants JavaException.class

yani bu yöntem 4 içindir ...

   protected int bad_method3(int, int) throws JavaException;
flags: ACC_PROTECTED
Code:
  stack=3, locals=3, args_size=3
     0: iload_1       
     1: iconst_3      
     2: if_icmpne     12
     5: aload_0       
     6: iload_1       
     7: iload_2       
     8: invokespecial #6                  // Method thrower:(II)I
    11: pop           
    12: aload_0       
    13: iload_1       
    14: iload_2       
    15: invokespecial #17                 // Method bad_method4:(II)I
    18: ireturn       
  LineNumberTable:
    line 63: 0
    line 64: 12
  StackMapTable: number_of_entries = 1
       frame_type = 12 /* same */

Exceptions:
  throws JavaException

13

ExceptionBir nullyığın izlemesi ile oluşturulması throwve try-catchbirlikte blok kadar zaman alır . Bununla birlikte, yığın izinin doldurulması ortalama 5 kat daha uzun sürer .

Performans üzerindeki etkisini göstermek için aşağıdaki ölçütleri oluşturdum. -Djava.compiler=NONEDerleyici optimizasyonunu devre dışı bırakmak için Yapılandırmayı Çalıştır'a ekledim . Yığın izini oluşturmanın etkisini ölçmek için, Exceptionsınıfı yığınsız kurucudan yararlanacak şekilde genişlettim :

class NoStackException extends Exception{
    public NoStackException() {
        super("",null,false,false);
    }
}

Kıyaslama kodu aşağıdaki gibidir:

public class ExceptionBenchmark {

    private static final int NUM_TRIES = 100000;

    public static void main(String[] args) {

        long throwCatchTime = 0, newExceptionTime = 0, newObjectTime = 0, noStackExceptionTime = 0;

        for (int i = 0; i < 30; i++) {
            throwCatchTime += throwCatchLoop();
            newExceptionTime += newExceptionLoop();
            newObjectTime += newObjectLoop();
            noStackExceptionTime += newNoStackExceptionLoop();
        }

        System.out.println("throwCatchTime = " + throwCatchTime / 30);
        System.out.println("newExceptionTime = " + newExceptionTime / 30);
        System.out.println("newStringTime = " + newObjectTime / 30);
        System.out.println("noStackExceptionTime = " + noStackExceptionTime / 30);

    }

    private static long throwCatchLoop() {
        Exception ex = new Exception(); //Instantiated here
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            try {
                throw ex; //repeatedly thrown
            } catch (Exception e) {

                // do nothing
            }
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long newExceptionLoop() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Exception e = new Exception();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long newObjectLoop() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Object o = new Object();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long newNoStackExceptionLoop() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            NoStackException e = new NoStackException();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

}

Çıktı:

throwCatchTime = 19
newExceptionTime = 77
newObjectTime = 3
noStackExceptionTime = 15

Bu, a oluşturmanın NoStackExceptionyaklaşık olarak tekrar tekrar atmak kadar pahalı olduğunu gösterir Exception. Ayrıca, bir Exceptionyığın izlemesi oluşturmanın ve doldurmanın yaklaşık 4 kat daha uzun sürdüğünü de gösterir .


1
Başlangıç ​​zamanından önce bir İstisna örneği oluşturduğunuzda bir vaka daha ekleyebilir ve ardından tekrar tekrar döngüde yakalayabilir misiniz? Bu sadece fırlatma + yakalamanın maliyetini gösterecektir.
Martin Carney

@MartinCarney Harika bir öneri! Bunu yapmak için cevabımı güncelledim.
Austin D

Test kodunuzda biraz değişiklik yaptım ve derleyici doğru numaraları almamızı engelleyen bazı optimizasyon yapıyor gibi görünüyor.
Martin Carney

@MartinCarney İndirim derleyici optimizasyonunun cevabını güncelledim
Austin D

Bilginize, muhtemelen Java'da doğru bir mikro ölçüt nasıl yazarım? İpucu: bu değil.
Daniel Pryden

4

Sorunun bu kısmı ...

Bunu sormanın bir başka yolu, bir İstisna örneği oluşturup tekrar tekrar atarsam, her attığımda yeni bir İstisna yaratmaktan çok daha hızlı olur mu?

Bir istisna oluşturup bir yere önbelleğe almayı isteyip istemediğinizi soruyor gibi görünüyor. Evet öyle. Nesne oluşturmada yazılan yığını kapatmakla aynıdır, çünkü zaten yapılmıştır.

Bunlar aldığım zamanlamalar, lütfen bundan sonra uyarı okuyun ...

|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%)|
|   16|            193|             251| 77 (%)| 
|   15|            390|             406| 96 (%)| 
|   14|            394|             401| 98 (%)| 
|   13|            381|             385| 99 (%)| 
|   12|            387|             370| 105 (%)| 
|   11|            368|             376| 98 (%)| 
|   10|            188|             192| 98 (%)| 
|    9|            193|             195| 99 (%)| 
|    8|            200|             188| 106 (%)| 
|    7|            187|             184| 102 (%)| 
|    6|            196|             200| 98 (%)| 
|    5|            197|             193| 102 (%)| 
|    4|            198|             190| 104 (%)| 
|    3|            193|             183| 105 (%)| 

Elbette bununla ilgili sorun, yığın izlemeniz şimdi nesneyi atıldığı yeri değil, nerede başlattığınızı gösteriyor.


3

@ AustinD'nin cevabını başlangıç ​​noktası olarak kullanarak bazı değişiklikler yaptım. En alttaki kod.

Bir Exception örneğinin art arda atıldığı durumu eklemeye ek olarak, doğru performans sonuçları alabilmemiz için derleyici optimizasyonunu da kapattım. Bu cevaba-Djava.compiler=NONE göre VM argümanlarına ekledim . (Tutulmada, bu VM bağımsız değişkenini ayarlamak için Yapılandırmayı Çalıştır → Bağımsız Değişkenleri düzenleyin)

Sonuçlar:

new Exception + throw/catch = 643.5
new Exception only          = 510.7
throw/catch only            = 115.2
new String (benchmark)      = 669.8

Bu nedenle, istisna oluşturmak, fırlatmak + yakalamak kadar yaklaşık 5 kat daha pahalıdır. Derleyicinin maliyetinin büyük bir kısmını optimize etmediğini varsayarsak.

Karşılaştırma için, optimizasyonu devre dışı bırakmadan aynı test çalıştırması şöyledir:

new Exception + throw/catch = 382.6
new Exception only          = 379.5
throw/catch only            = 0.3
new String (benchmark)      = 15.6

Kod:

public class ExceptionPerformanceTest {

    private static final int NUM_TRIES = 1000000;

    public static void main(String[] args) {

        double numIterations = 10;

        long exceptionPlusCatchTime = 0, excepTime = 0, strTime = 0, throwTime = 0;

        for (int i = 0; i < numIterations; i++) {
            exceptionPlusCatchTime += exceptionPlusCatchBlock();
            excepTime += createException();
            throwTime += catchBlock();
            strTime += createString();
        }

        System.out.println("new Exception + throw/catch = " + exceptionPlusCatchTime / numIterations);
        System.out.println("new Exception only          = " + excepTime / numIterations);
        System.out.println("throw/catch only            = " + throwTime / numIterations);
        System.out.println("new String (benchmark)      = " + strTime / numIterations);

    }

    private static long exceptionPlusCatchBlock() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            try {
                throw new Exception();
            } catch (Exception e) {
                // do nothing
            }
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long createException() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Exception e = new Exception();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long createString() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Object o = new String("" + i);
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long catchBlock() {
        Exception ex = new Exception(); //Instantiated here
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            try {
                throw ex; //repeatedly thrown
            } catch (Exception e) {
                // do nothing
            }
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }
}

Optimizasyonu devre dışı bırakma = harika teknik! Kimseyi yanıltmamak için orijinal cevabımı düzenleyeceğim
Austin D

3
Optimizasyonu devre dışı bırakmak, hatalı bir karşılaştırma ölçütü yazmaktan daha iyi değildir, çünkü saf yorumlanan modun gerçek dünya performansı ile ilgisi yoktur. JVM'nin gücü JIT derleyicisidir, bu yüzden gerçek uygulamanın nasıl çalıştığını yansıtmayan bir şeyi ölçmenin anlamı nedir?
apangin

2
İstisnalar yaratmanın, fırlatmanın ve yakalamanın bu 'karşılaştırmalı değerlendirmede' dönüştürülenden çok daha fazla yönü vardır. Şiddetle okumanızı öneririm bu yazı .
Mart'ta apangin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.