2010-10-09 26 views
9

Bir performans artışı elde etmek ve çalıştırmak için C# kodunun en küçük miktarı nedir?En Kolay Muhtemel Performans Sayacı Örneği

Kodumdaki iki nokta arasındaki CPU döngü sayısını ve/veya süreyi ölçmek istiyorum. Web üzerindeki tüm gözleme ile yağma yaptım ama böyle bir önemsiz görev için gerekli olandan daha fazla kod gibi görünüyor. Sadece çabucak bir ölçüm yapmak, koşmak ve üzerinde çalıştığım şeye daha fazla odaklanmak istiyorum.

cevap

26

Bunun için bir performans sayacına ihtiyacınız olduğunu düşünmüyorum. StopWatch'dan alabileceğiniz zamanlamadan daha fazlasına ihtiyacınız var mı? Bu çok doğru.

Stopwatch watch = Stopwatch.StartNew(); 

// Do work 

watch.Stop(); 
// elapsed time is in watch.Elapsed 

Ancak, aslında sorulan soruya cevap vermek: Sadece mevcut sayaçlarını sorgulamak istiyorsanız, aslında oldukça basittir.

using System; 
using System.Diagnostics; 
using System.Linq; 

static class Test 
{ 
    static void Main() 
    { 
     var processorCategory = PerformanceCounterCategory.GetCategories() 
      .FirstOrDefault(cat => cat.CategoryName == "Processor"); 
     var countersInCategory = processorCategory.GetCounters("_Total"); 

     DisplayCounter(countersInCategory.First(cnt => cnt.CounterName == "% Processor Time")); 
    } 

    private static void DisplayCounter(PerformanceCounter performanceCounter) 
    { 
     while (!Console.KeyAvailable) 
     { 
      Console.WriteLine("{0}\t{1} = {2}", 
       performanceCounter.CategoryName, performanceCounter.CounterName, performanceCounter.NextValue()); 
      System.Threading.Thread.Sleep(1000); 
     } 
    } 
} 

Elbette, süreç ihtiyacınız performans sayaçlarını erişmek için uygun olanı izinleri gerekir: Burada tam bir örnektir.

+0

Belki de basit bir Regex motorunu uygulamaya çalıştığımı açıklamalıydım. Durma saati bunun için yeterince doğru olacak mı? –

+0

@Paul Matthews - iyi olacak. Kronometre çözünürlüğü – Oded

+1

numaralı kronometredir. Kodunuzun performansını ölçmek için yeterince doğru, eğer sormak istediğiniz buysa. Performansı ölçüyorsanız, Visual Studio dışındaki Sürüm modunda kod çalıştırmayı unutmayın. Ayrıca, performansı ölçmek için bir profil oluşturucu kullanmanızı tavsiye ederim, kodun performansıyla ilgili basit bir noktadan noktaya zaman ölçümünden çok daha fazlasını anlatacağım. – driis

2

Bunu, .NET'te çalıştırmak ve çalıştırmak için önemsiz yol yoktur. Ancak, bulduğum en basit yol, performans sayaçlarıyla çalışmak için bazı yetenekleri sağlayan Kurumsal Kütüphane'nin üzerine inşa etmektir. Örneğin, the Performance Counter Handler

Enterprise Library, performans sayaçlarının kurulumunu daha kolay yönetmek için bazı özellikler de sunar. Bu sadece kod saklanması verir

private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounter = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTime); 
private static EnterpriseLibraryPerformanceCounter averageRequestTimeCounterBase = PerformanceCounterManager.GetEnterpriseLibraryCounter(MadPerformanceCountersListener.AverageRequestTimeBase); 

public void DoSomethingWeWantToMonitor() 
{ 
    using (new AverageTimeMeter(averageRequestTimeCounter, averageRequestTimeCounterBase)) 
    { 
     // code here that you want to perf mon 
    } 
} 

Bir de izlemek istiyorum:

Ayrıca, bunu yapmak sadece sağlayan bir AvergeTimeMeter oluşturabilir, Diyelim ki bu yüzden bunun üzerine inşa edelim blok kullanarak - ve tüm performans sayacı altyapısı hakkında endişelenmekten ziyade üzerinde çalışmak istediğiniz kod üzerinde yoğunlaşın.

Bunu yapmak için, aşağıdaki gibi yeniden kullanılabilir AverageTimeMeter sınıfını oluşturacağız:

public sealed class AverageTimeMeter : IDisposable 
{ 
    private EnterpriseLibraryPerformanceCounter averageCounter; 
    private EnterpriseLibraryPerformanceCounter baseCounter; 
    private Stopwatch stopWatch; 
    private string instanceName; 

    public AverageTimeMeter(EnterpriseLibraryPerformanceCounter averageCounter, EnterpriseLibraryPerformanceCounter baseCounter, string instanceName = null) 
    { 
     this.stopWatch = new Stopwatch(); 
     this.averageCounter = averageCounter; 
     this.baseCounter = baseCounter; 
     this.instanceName = instanceName; 
     this.stopWatch.Start(); 
    } 

    public void Dispose() 
    { 
     this.stopWatch.Stop(); 
     if (this.baseCounter != null) 
     { 
      this.baseCounter.Increment(); 
     } 

     if (this.averageCounter != null) 
     { 
      if (string.IsNullOrEmpty(this.instanceName)) 
      { 
       this.averageCounter.IncrementBy(this.stopWatch.ElapsedTicks); 
      } 
      else 
      { 
       this.averageCounter.SetValueFor(this.instanceName, this.averageCounter.Value + this.stopWatch.ElapsedTicks); 
      } 
     } 
    } 

} 

Sen (EntLib örneklerde gösterildiği) performans sayaçlarını kaydetmek zorunda ama bu başlangıç ​​yapmanız.

+0

Yukarıda görüldüğümüz yorumlara dayanarak, belki de sizin sorularınızın kod ölçme ile ilgili olduğunu ve çok fazla değil * performans sayaçlarıyla ilgili olduğunu görüyoruz. Ben her zaman özellikle performans sayaçlarının perspektifinden bir soru - eğer buna ihtiyacınız yoksa, bu Kronometre'nin gitmenin en basit yolu olduğuna katılıyorum. –

+0

En son kullandığım performans sayaçları Delphi'ydi, belki de terminoloji biraz değişti. Üzgünüm, size bahçe yolunu yönlendirdim :) –

-1

Sayaç olarak adlandırılan statik değişkeni uzun süre yapabilir ve bunu artıran bir iş parçacığı oluşturabilirsiniz. İstediğiniz zaman ve/veya ihtiyacınız olduğunda bu iş parçacığı başlatabilir ve iptal edebilirsiniz. İş parçacığı çalışırken, CPU döngülerinin sayısını ve/veya kodunuzdaki iki nokta arasındaki süreyi ölçmek için statik sayacın tamsayı değerini kullanabilirsiniz. İş parçacığı ve statik sayaç tekniği Kronometre Başlat Durdur Yeniden Başlatma Sıfırlama yöntemlerinin ve ElapsedTicks öğesinin kullanımıyla karşılaştırılabilir.

+1

İlginç bir yaklaşım gibi geliyor. CPU döngülerini ölçmek için başka bir iş parçacığı kullanmanın bize kesin bir ölçüm yapmasını nasıl sağlayacağını gerçekten anlamıyorum. İş parçacığının, ölçtüğümüz iş parçacığıyla tam olarak aynı CPU zaman dilimini kapladığı garanti edilir mi? –

6

Ben herhangi bir kod bloğunu almak ve süreyi ölçmek için kronometre profilleme kodu ile sarın şey ister onu infaz harcanan:

using System.Diagnostics; 
    using System.Threading; 

    public static T Profile<T>(Func<T> codeBlock, string description = "") 
    { 
     Stopwatch stopWatch = new Stopwatch(); 
     stopWatch.Start(); 
     T res = codeBlock(); 
     stopWatch.Stop(); 
     TimeSpan ts = stopWatch.Elapsed; 
     const double thresholdSec = 2; 
     double elapsed = ts.TotalSeconds; 
     if(elapsed > thresholdSec) 
      System.Diagnostics.Debug.Write(description + " code was too slow! It took " + 
      elapsed + " second(s)."); 
     return res; 
    } 

Sonra böyle diyoruz:

Profile(() => MyObj.MySlowMethod()); 

ya:

Profile(() => MyObj.MySlowMethod(), "I can explain why"); 
+0

Gerçekten çok güzel! –

İlgili konular