Bir yöntemin yürütme süresini hesaplama


Yanıtlar:


1131

Stopwatch bu amaç için tasarlanmıştır ve .NET'te zaman yürütülmesini ölçmenin en iyi yollarından biridir.

var watch = System.Diagnostics.Stopwatch.StartNew();
// the code that you want to measure comes here
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;

Do DateTime kullanmak .NET zaman yürütülmesine ölçmek için.


GÜNCELLEME:

Yorumlar bölümünde @ series0ne tarafından belirtildiği gibi: Bazı kodların yürütülmesinin kesin bir ölçümünü yapmak istiyorsanız, işletim sisteminde yerleşik olan performans sayaçlarını kullanmanız gerekir. Aşağıdaki cevabı güzel bir bakış içerir.


2
Tam olarak ve bu durumda ne var: ben bir ThreadPool.QueueUserWorkItem(delegate { CopyFiles(folder, dest); }); iç, ancak her şey yapılmadan önce kronometre durur bir foreach döngü var .
Mehdi Tahsildari

13
@DarinDimitrov - Kronometre tamamen doğru değil mi? .NET arka plan gürültüsünün (JITing gibi) değişen yürütme sürelerinin oluşmasına neden olduğunu unutmayın. Bu nedenle, gerçekçi bir şekilde, doğru ölçümler için OP bir performans profili kullanmalıdır.
Matthew Layton

3
@ series0ne, çok iyi bir nokta. Cevabınızı değerli yorumunuzu içerecek şekilde güncelleyeceğim.
Darin Dimitrov

7
@DarinDimitrov, son zamanlarda çok yetenekli bir üst düzey geliştiriciyle röportaj yaptım. DateTimes kullanmanın aslında bir StopWatch kullanmaktan daha doğru olduğuna dikkat çekti. Bunun sebebinin .NET'teki Kronometrenin CPU benzeşimini hesaba katmaması ve bu nedenle iş parçacığınız bir çekirdekten diğerine hareket ederse, StopWatch diğer çekirdeklerdeki yürütme süresini dikkate almaz; sadece iş parçacığının yürütülmeye başladığı yer. Bu konudaki fikriniz nedir?
Matthew Layton

2
@ series0ne, üst düzey geliştiricinin size Kronometre ve DateTime hakkında söyledikleri kesinlikle doğrudur. Bunun dışında DateTime ile yeterli hassasiyete sahip değilsiniz. Sorun, .NET'te tüm bu özelliklere izin verecek böyle bir sınıf olmamasıdır.
Darin Dimitrov

75

Kişisel deneyimden, System.Diagnostics.Stopwatchsınıf bir yöntemin yürütme süresini ölçmek için kullanılabilir, ancak DİKKAT : Tamamen doğru değildir!

Aşağıdaki örneği düşünün:

Stopwatch sw;

for(int index = 0; index < 10; index++)
{
    sw = Stopwatch.StartNew();
    DoSomething();
    Console.WriteLine(sw.ElapsedMilliseconds);
}

sw.Stop();

Örnek sonuçlar

132ms
4ms
3ms
3ms
2ms
3ms
34ms
2ms
1ms
1ms

Şimdi merak ediyorsunuz; "Peki neden ilk seferinde 132 ms sürdü ve geri kalan süre önemli ölçüde daha az?"

Cevap, StopwatchJITing gibi .NET'te "arka plan gürültüsü" etkinliğini telafi etmemesidir. Bu nedenle, yönteminizi ilk kez çalıştırdığınızda, .NET JIT ilk önce. Bunu yapmak için gereken süre, yürütme zamanına eklenir. Aynı şekilde, diğer faktörler de yürütme süresinin değişmesine neden olacaktır.

Mutlak doğruluk için aradığınız şey Performans Profili Oluşturma !

Aşağıdakilere bir göz atın:

RedGate ANTS Performance Profiler ticari bir üründür, ancak çok doğru sonuçlar verir. - .NET profili oluşturma ile uygulamalarınızın performansını artırın

İşte profilleme üzerine bir StackOverflow makalesi: - Bazı İyi .NET Profilers nelerdir?

Ayrıca bakmak isteyebileceğiniz Kronometre kullanarak Performans Profili Oluşturma hakkında bir makale yazdım - .NET'te performans profili oluşturma


2
@mahditahsildari Sorun yok. Yardımcı olduğuma sevindim! :-)
Matthew Layton

41
Bunun neden bir yanlışlık örneği olduğundan emin değilim . Kronometre, ilk çağrının toplam maliyetini doğru bir şekilde ölçüyor, bu da kesinlikle bu kodu çalıştıracak olan müşteriyle ilgili. 132 milisaniyenin metodun yürütülmesine mi yoksa jitter'e mi yüklendiğini umursamıyorlar, geçen toplam süreyi önemsiyorlar.
Eric Lippert

2
@ series0ne Bir döngünün performansını önemsiyorsanız, bir döngünün performansını ölçün. Bir şeyi n kez yapmanın, bir kez yürütmenin tam olarak n kat daha yavaş olacağı anlamına geldiğini düşünmeyin .
Aralık'ta svick

3
İlk olarak, kod örneği StopWatch döngüde asla sıfırlanmadığından, sürekli artan bir sayı ile çıktı üretmelidir. Ve "gerekir" demek istediğim (kontrol ettim). Böylece çıktınız kodla eşleşmiyor. İkincisi, döngüde bir Durdur / Yaz / Sıfırla / Başlat yapmak için kodu düzelttiğimde, ilk ölçüm diğerleriyle aynı oldu. Sanırım DoSomething'iniz ilk kez daha uzun süre bir şeyler yapıyor. JIT bunun nedeni olabilir veya olmayabilir, ancak Kronometre ölçümü etkilemez. Dolayısıyla -1.
ILIA BROUDNO

2
ILIA BROUDNO kesinlikle doğru, aynı sonuçları aldım. @ series0ne, ms içinde bugüne kadar döngü içinde bir Console.WriteLine var; çünkü saati sadece döngü sona erdikten SONRA durdurursunuz, her yinelemeyle zaman içinde artmaktadır, bu yüzden zaman, yürütmeler üzerinde biriktikçe 3, 6, 10, 12, 15 gibi bir şey görmeliyiz.
Rui Miguel Pinheiro

29

StopWatch sınıfı en iyi çözümünüzü arar.

Stopwatch sw = Stopwatch.StartNew();
DoSomeWork();
sw.Stop();

Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);

Ayrıca adlı statik bir alanı vardır Stopwatch.IsHighResolution. Tabii ki, bu bir donanım ve işletim sistemi sorunudur.

Zamanlayıcının yüksek çözünürlüklü performans sayacına bağlı olup olmadığını gösterir.


18

Performansı anlamakla ilgileniyorsanız, en iyi cevap profiler kullanmaktır.

Aksi takdirde, System.Diagnostics.StopWatch yüksek çözünürlüklü bir zamanlayıcı sağlar.


Kesinlikle doğru! Biraz cesaretim yok, buradaki pek çok kişi tamamen doğru olmadığı için Kronometreyi kullanmayı önerdi. Ancak bir Performance profiler kullanmanızı önerdiğiniz gibi, bunu yapmanın doğru yolu budur! +1
Matthew Layton

7

StopWatch yüksek çözünürlüklü sayacı kullanacaktır

Kronometre, alttaki zamanlayıcı mekanizmasındaki zamanlayıcı kenelerini sayarak geçen zamanı ölçer. Kurulu donanım ve işletim sistemi yüksek çözünürlüklü bir performans sayacını destekliyorsa, Kronometre sınıfı geçen süreyi ölçmek için bu sayacı kullanır. Aksi takdirde, Kronometre sınıfı geçen süreyi ölçmek için sistem zamanlayıcıyı kullanır. Kronometre zamanlaması uygulamasının kesinliğini ve çözünürlüğünü belirlemek için Frekans ve IsHighResolution alanlarını kullanın.

ES'yi ölçüyorsanız, rakamlarınız büyük olasılıkla dış olaylardan etkilenecektir ve çok endişeleniyorum. doğruluk (yukarıda belirttiğiniz gibi). Bunun yerine bir dizi ölçüm alırdım ve bu rakamların ortalamasını ve dağılımını düşünürdüm.


0
 using System.Diagnostics;
 class Program
 {
    static void Test1()
    {
        for (int i = 1; i <= 100; i++)
        {
            Console.WriteLine("Test1 " + i);
        }
    }
  static void Main(string[] args)
    {

        Stopwatch sw = new Stopwatch();
        sw.Start();
        Test1();
        sw.Stop();
        Console.WriteLine("Time Taken-->{0}",sw.ElapsedMilliseconds);
   }
 }
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.