BenchmarkDotNet ile Metotların Çalışma Hızını Test Edin
Günlük hayatta yazdığımız algoritmalar için karmaşıklık analizini büyük O notasyonu cinsinden hesaplayabiliyoruz. Peki yazdığımız O(n) karmaşıklığına sahip bir kod gerçekten ne kadar hızlı ve hangi sürelerde yanıt veriyor? Bu gibi istatistiklerin tutulması ve programcı tarafından hesaplanması ek bir yük getiriyor. Örneğin aşağıdaki kodu ele alalım:
public class Toplayici
{
private const int limitSayi = 1000000;
public int Topla()
{
int toplam = 0;
for (int i = 0; i < limitSayi; i++)
{
toplam += i;
}
return toplam;
}
}
Kodda gördüğümüz gibi 1 milyona kadar olan sayılar art arda toplanıyor ve sonuç geri döndürüyor. Her zamanki kullandığımız geleneksel metodlarla (bkz: Stopwatch kullanımı) test kodumuz aşağıdaki hali alacaktır:
public class Program
{
static void Main()
{
Stopwatch s1 = Stopwatch.StartNew();
new Toplayici().Topla();
s1.Stop();
Stopwatch s2 = Stopwatch.StartNew();
new Toplayici().Topla();
s2.Stop();
Stopwatch s3 = Stopwatch.StartNew();
new Toplayici().Topla();
s3.Stop();
Console.WriteLine("{0}ms, {1}ms, {2}ms",
s1.ElapsedMilliseconds,
s2.ElapsedMilliseconds,
s3.ElapsedMilliseconds);
Console.Read();
}
}
3 kere çalıştırıp sonuçları ekrana yazdırmayı başardık. Gayet temiz bir şekilde ölçümleme yapmış olduk. Fakat Toplayici
sınıfımızın içerisine bir tane daha metod ekleseydik ve onu da ölçümlemeye çalışsaydık Main() fonksiyonumuzun satır sayısı 2 katına çıkacaktı. Bu şekilde birçok metodumuzun olduğu durumlarda benchmarking işlemi oldukça karmaşık bir hâl almaya başlıyor. Hele ki sonuçların alınıp dosyaya yazılması, Excel’e aktarılması gibi diğer angarya işler de ortaya çıkmaya başlıyor. Peki neden bu tarz repetative işleri bir kod kütüphanesine yaptırmayalım?
Çare BenchmarkDotNet
Dotnet Foundation‘ın çıkardığı BenchmarkDotNet, bir .NET kütüphanesi olup performans ölçüm işlemlerinde kullanılmaktadır. Bir önceki paragrafta da bahsettiğimiz gibi bütün angarya işleri gerçekleştirerek, deneyimli yazılımcıların bile düştüğü yaygın hatalardan uzak tutar. Her ölçümlenecek metod için izole bir proje oluşturur, oluşturduğu projeyi defalarca kez başlatır ve aynı metodu döngüler içerisinde çalıştırır. BenchmarkDotNet, istenen hassasiyet seviyesini otomatik olarak seçtiği için metodların kaç defa çalıştırılacağının seçilmesine genellikle gerek yoktur.
Şimdi gelin NuGet paket yöneticisi üzerinden BenchmarkDotNet’i projemize dahil edelim:
Performans ölçümü için yapmamız gereken sadece ölçümlenecek metodun üzerine [Benchmark]
Attribute’ünü eklemek.
public class Toplayici
{
private const int limitSayi = 1000000;
[Benchmark]
public int Topla()
{
int toplam = 0;
for (int i = 0; i < limitSayi; i++)
{
toplam += i;
}
return toplam;
}
}
Kodumuza sadece tek bir satır ekledik. Sıra şsimdi ise Main() metodunda ilgili değişikliği gerçekleştirmeye geldi.
public class Program
{
static void Main()
{
BenchmarkRunner.Run<Toplayici>();
}
}
Üstteki şekilde sadece tek bir satır ekleyerek performans ölçüm için kodumuzu hazır hale getirdik. Şimdi ise projemizi Release modunda Build edelim ve cmd.exe üzerinden çalıştıralım:
Gördüğümüz gibi metodun döngü sayısını 1024 olarak ayarladı ve 15’er defa projeyi çalıştırdı. Çıkan sonucu ekrana yazdırarak görevini tamamlayan BenchmarkDotNet, aynı zamanda bizim için CSV, Markdown ve HTML dosyalarını Release\BenchmarkDotNet.Artifacts\results dizini içerisinde oluşturdu:
HTML dosyasını açtığınızda çalıştırdığınız makine ile ilgili bilgilerin yanında, metodun performans ölçümü ile ilgili ortalama, hata ve standart sapma değerlerinin bulunduğu tabloya ulaşabilirsiniz:
Bu yazımızda da .NET projelerinde performans ölçümleme işlemlerinde kullanabileceğiniz BenchmarkDotNet’i tanıtmaya çalıştık. BenchmarkDotNet hakkındaki düşüncelerinizi aşağıdaki yorum kısmında bizimle paylaşabilirsiniz. Bir başka yazıda görüşmek üzere.
2 Comments
HAKAN OZER
25 Eylül 2017 at 16:26Merhaba,
Paylaşım için çok teşekkür ederim.
Zafer Ayan
12 Ekim 2017 at 13:48Rica ederim.