Java programı yürütme hızı nasıl zamanlanır


85

Bir java programının çalıştırılma zamanını nasıl alırsınız? Bunu yapmak için hangi sınıfı kullanmam gerektiğinden emin değilim.

Ben şöyle bir şey arıyorum:

// Some timer starts here
for (int i = 0; i < length; i++) {
  // Do something
}
// End timer here

System.out.println("Total execution time: " + totalExecutionTime);

Yanıtlar:


139
final long startTime = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
  // Do something
}
final long endTime = System.currentTimeMillis();

System.out.println("Total execution time: " + (endTime - startTime));

2
gerçekten nanoTime olmalı
Eugene

6
NanoTime olmamalıdır. Rhu'nun cevabına bakın.
fabspro

4
Burada "final" i kullanmanızın özel bir nedeni var mı? Bu anahtar kelimeyi çıkarırsanız ne farklı olurdu?
dijxtra

9
@dijxtra kullanmak final, yanlışlıkla ona atama yapamama avantajına sahiptir (anonim sınıf erişimi gibi diğer avantajların yanı sıra). Bu kodda bir fark yaratmaz. Her şeyi yapmak oldukça yaygın bir uygulamadır finalve sadece finalihtiyacınız olduğunda onu çözmek.
wchargin

1
Test edilecek kod, zaman ölçümleri ile birlikte birçok kez çalıştırılmalı ve ilk sonuç atılmalıdır. İlki muhtemelen sınıf yükleme sürelerini vb. İçerecektir. Bunu birden çok kez çalıştırarak, tabii ki daha yararlı ve güvenilir bir ortalama elde edersiniz.
Arun Ramakrishnan

34

System#nanoTime()Geçen süreyi kaydetmek için çok çekirdekli CPU'larda güvenilir bir şekilde kullanılamayan bazı sorunlar olduğunu unutmayın ... her bir çekirdek kendi TSC'sini ( Zaman Damgası Sayacı ) korur : bu sayaç nano zamanı elde etmek için kullanılır (gerçekten CPU önyüklendiğinden beri yapılan işaretlerin sayısı).

Bu nedenle, işletim sistemi çekirdekleri eşzamanlı tutmak için bir miktar TSC zaman atlaması yapmadıkça, ilk zaman okuması alındığında bir çekirdek üzerinde bir iş parçacığı programlanırsa, ardından farklı bir çekirdeğe geçilirse, göreceli zaman düzensiz olarak geriye doğru atlıyor gibi görünebilir. ve ileriye.

Bunu bir süre önce AMD / Solaris'te iki zamanlama noktası arasında geçen sürelerin bazen negatif değerler veya beklenmedik şekilde büyük pozitif sayılar olarak geri geldiğini gözlemledim. Solaris çekirdek yaması ve AMD PowerNow'u zorlamak için BIOS ayarı gerekliydi! kapatıldı, bu da çözdü.

Ayrıca, System#nanoTime()bir VirtualBox ortamında java kullanırken şu ana kadar düzeltilmemiş bir hata (AFAIK) vardır ; java.util.concurrencyPaketin çoğu nano zamana bağlı olduğu için bizim için her türlü tuhaf aralıklı iş parçacığı sorunlarına neden oluyor .

Ayrıca bakınız:

System.nanoTime () tamamen işe yaramaz mı? http://vbox.innotek.de/pipermail/vbox-trac/2010-January/135631.html


9

Geçerli sistem saatini milisaniye cinsinden alırsınız:

final long startTime = System.currentTimeMillis();

Sonra ne yapacaksan onu yap:

for (int i = 0; i < length; i++) {
  // Do something
}

Sonra ne kadar sürdüğünü görüyorsunuz:

final long elapsedTimeMillis = System.currentTimeMillis() - startTime;

BalusC'un yanıtı da doğrudur; gerekli zamanlayıcı çözünürlüğüne ve neden zamanlamaya ihtiyacınız olduğuna bağlıdır.
Jonathan Feinberg

9

Yararlanabilirsiniz System#nanoTime(). İnfazdan önce ve sonra alın ve sadece hesaplayın. Yukarıda tercih edilir System#currentTimeMillis()çünkü daha iyi bir hassasiyete sahiptir. Kullanılan donanıma ve platforma bağlı olarak, aksi takdirde geçen sürede yanlış bir boşlukla karşılaşabilirsiniz. Burada Windows üzerinde Core2Duo ile yaklaşık 0 ile ~ 15ms arasında hiçbir şey hesaplanamaz.

Daha gelişmiş bir araç profilleyicidir .


Windows'taki zamanlayıcı, varsayılan olarak özellikle iyi bir çözünürlüğe sahip değildir. Orada olan yüksek performanslı bir zamanlayıcı da ama çok daha zordur C'den bile kullanmak ve Java (AFAIK) bir JNI olmadan hackery bir seviye thunk o düşük seviyesine erişimi sağlamaz.
Donal Fellows

1
nanoTime()bir sorunu var (en azından Windows'ta); zaman damgası işlemci çekirdeğine özeldir. Bir çekirdekte "başlangıç" zaman damgasını ve başka bir çekirdekte "durdurma" zaman damgasını aldığı için çalıştırma süresi negatif olan bir programım vardı.
gustafc

3

Basit şeyler için System.currentTimeMillis () çalışabilir.

Aslında o kadar yaygındır ki IDE'm "t0" girildiğinde bana aşağıdaki satırı oluşturur:

final long t0 = System.currentTimeMillis()

Ancak daha karmaşık şeyler için, muhtemelen burada olduğu gibi istatistiksel zaman ölçümlerini kullanmak isteyeceksiniz (biraz aşağı kaydırın ve standart sapmalar dahil olmak üzere ifade edilen zaman ölçümlerine bakın vb.):

http://perf4j.codehaus.org/devguide.html


Otomatik oluşturucu kodunu göstermek için +1. Her zaman benzer bir ifade kullanıyorum ve kod şablonlarını eklemeyi bilmiyordum. Tutulma ile bunu nasıl yapacağınızı öğrendim ve kesinlikle yardımcı olacaktır!
Jason

Tüm Codehaus hizmetleri sonlandırıldı. Bağlantınız artık kesildi.
naXa

2

AOP / AspectJ ve jcabi yönlerinden@Loggable ek açıklama kullanarak, bunu kolay ve kompakt bir şekilde yapabilirsiniz:

@Loggable(Loggable.DEBUG)
public String getSomeResult() {
  // return some value
}

Bu yönteme yapılan her çağrı, DEBUGgünlük kaydı seviyesiyle SLF4J günlük kaydı tesisine gönderilecektir . Ve her günlük mesajı yürütme zamanını içerecektir.


2

Java'da yürütme zamanını bulmanın birkaç yolu:

1) System.nanoTime ()

long startTime = System.nanoTime();
.....your code....
long endTime   = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in nanoseconds  : " + totalTime);
System.out.println("Execution time in milliseconds : " + totalTime / 1000000);

2) System.currentTimeMillis ()

long startTime = System.currentTimeMillis();
.....your code....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds  : " + totalTime);

3) Instant.now ()

long startTime = Instant.now().toEpochMilli();
.....your code....
long endTime = Instant.now().toEpochMilli();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

veya

Instant start = Instant.now();
.....your code....
Instant end = Instant.now();
Duration interval = Duration.between(start, end);
System.out.println("Execution time in seconds: " +interval.getSeconds());

4) Date.getTime ()

long startTime = new Date().getTime();
.....your code....
long endTime = new Date().getTime();
long totalTime = endTime - startTime;
System.out.println("Execution time in milliseconds: " + totalTime);

1

startTime=System.currentTimeMillis()Döngünün en üstünde, başlangıç ​​zamanı için uzun kullanın

long endTime= System.currentTimeMillis();döngünün sonunun dışına koyun . Çalışma zamanını milisaniye cinsinden elde etmek için değerleri çıkarmanız gerekecek.

Nanosaniye cinsinden zaman istiyorsanız, kontrol edin System.nanoTime()


1

Ölçmek istediğiniz kodu lambda olarak / olarak alan daha yüksek dereceli bir fonksiyon oluşturdum:

class Utils {

    public static <T> T timeIt(String msg, Supplier<T> s) {
        long startTime = System.nanoTime();
        T t = s.get();
        long endTime = System.nanoTime();
        System.out.println(msg + ": " + (endTime - startTime) + " ns");
        return t;
    }

    public static void timeIt(String msg, Runnable r) {
       timeIt(msg, () -> {r.run(); return null; });
    }
}

Şöyle diyelim:

Utils.timeIt("code 0", () ->
        System.out.println("Hallo")
);

// in case you need the result of the lambda
int i = Utils.timeIt("code 1", () ->
        5 * 5
);

Çıktı:

kod 0: 180528 ns
kod 1: 12003 ns

Fazlalıkları azaltmama yardım eden Andy Turner'a özel teşekkürler . Buraya bakın .



0

Perf4J'yi de deneyebilirsiniz. Bu, aradığınızı yapmanın düzgün bir yoludur ve ortalama, minimum, maksimum, standart sapma ve belirli bir zaman aralığı boyunca saniye başına işlemler gibi toplu performans istatistiklerine yardımcı olur. Http://perf4j.codehaus.org/devguide.html'den bir alıntı :

StopWatch stopWatch = new LoggingStopWatch();

try {
    // the code block being timed - this is just a dummy example
    long sleepTime = (long)(Math.random() * 1000L);
    Thread.sleep(sleepTime);
    if (sleepTime > 500L) {
        throw new Exception("Throwing exception");
    }

    stopWatch.stop("codeBlock2.success", "Sleep time was < 500 ms");
} catch (Exception e) {
    stopWatch.stop("codeBlock2.failure", "Exception was: " + e);
}

Çıktı:

INFO: start[1230493236109] time[447] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493236719] time[567] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493237286] time[986] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493238273] time[194] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238467] time[463] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493238930] time[310] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239241] time[610] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]
INFO: start[1230493239852] time[84] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239937] time[30] tag[codeBlock2.success] message[Sleep time was < 500 ms]
INFO: start[1230493239968] time[852] tag[codeBlock2.failure] message[Exception was: java.lang.Exception: Throwing exception]

0
public class someClass
{
   public static void main(String[] args) // your app start point
   {
       long start = java.util.Calendar.getInstance().getTimeInMillis();

       ... your stuff ...

       long end = java.util.Calendar.getInstance().getTimeInMillis();
       System.out.println("it took this long to complete this stuff: " + (end - start) + "ms");
   }
}

0

System.currentTimeMillis () kullanmak bunu yapmanın doğru yoludur. Ancak, komut satırı kullanıyorsanız ve tüm programı yaklaşık ve hızlı bir şekilde zamanlamak istiyorsanız, şunları düşünün:

time java App

Bu, Uygulamanızda kodu ve saati değiştirmemenizi sağlar.


Bu, kodu nasıl çalıştırdığınıza bağlıdır. Bir sunucuyu çalıştıran bir kod parçasıysa, yanlış olan başlangıç ​​zamanını dahil edeceksiniz.
Arun Ramakrishnan
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.