BenchmarkDotNet: .NET Performans Ölçüm Kütüphanesi

Performans, modern yazılım geliştirme süreçlerinde önemli bir faktördür. Kodun ne kadar hızlı çalıştığını anlamak ve iyileştirmek için doğru araçları kullanmak gerekir. .NET ekosisteminde bu amaçla kullanılan en popüler araçlardan biri BenchmarkDotNet’tir. Bu makalede, BenchmarkDotNet’in ne olduğunu, nasıl kurulduğunu ve kullanıldığını, ayrıca çeşitli kullanım senaryolarını inceleyeceğiz.

BenchmarkDotNet Nedir?

BenchmarkDotNet, .NET uygulamaları için performans testi yapmayı kolaylaştıran güçlü bir kütüphanedir. Kod parçacıklarının performansını ölçmek, karşılaştırmak ve analiz etmek için kullanılan bu araç, yüksek doğrulukta ve tekrarlanabilir sonuçlar sağlar. BenchmarkDotNet, mikro benchmark’lar (küçük ve izole edilmiş kod parçacıkları) üzerinde çalışır ve kodunuzun gerçek performansını anlamanıza yardımcı olur.

BenchmarkDotNet Kurulumu

BenchmarkDotNet kütüphanesini projeye eklemek oldukça basittir. .NET CLI veya Visual Studio kullanarak NuGet paket yöneticisi ile kurulabilir.

.NET CLI ile Kurulum

dotnet add package BenchmarkDotNet

Visual Studio ile Kurulum

  1. Proje dosyanıza sağ tıklayın.
  2. “Manage NuGet Packages” seçeneğini seçin.
  3. “Browse” sekmesinde “BenchmarkDotNet” aratın.
  4. BenchmarkDotNet paketini seçin ve “Install” butonuna tıklayın.

BenchmarkDotNet Kullanımı

BenchmarkDotNet kullanarak performans testleri yazmak için öncelikle bir benchmark sınıfı oluşturmalısınız. Bu sınıf, performansını ölçmek istediğiniz metotları içerir ve BenchmarkDotNet öznitelikleri (attributes) kullanılarak yapılandırılır.

Basit Bir Benchmark Örneği

Aşağıdaki örnek, iki farklı metot arasındaki performans farkını ölçmek için basit bir benchmark sınıfı oluşturur:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Linq;

public class Benchmarks
{
    private int[] numbers;

    [GlobalSetup]
    public void Setup()
    {
        numbers = Enumerable.Range(0, 1000).ToArray();
    }

    [Benchmark]
    public int SumWithForLoop()
    {
        int sum = 0;
        for (int i = 0; i < numbers.Length; i++)
        {
            sum += numbers[i];
        }
        return sum;
    }

    [Benchmark]
    public int SumWithLinq()
    {
        return numbers.Sum();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<Benchmarks>();
    }
}

BenchmarkDotNet Öznitelikleri

BenchmarkDotNet, performans testlerinizi yapılandırmak için çeşitli öznitelikler sunar. İşte en yaygın kullanılan özniteliklerden bazıları:

  • [Benchmark]: Performansını ölçmek istediğiniz metotlara uygulanır.
  • [GlobalSetup]: Benchmark çalıştırılmadan önce bir kez çalıştırılan metotlara uygulanır. Test verilerini hazırlamak için kullanılır.
  • [GlobalCleanup]: Benchmark çalıştırıldıktan sonra bir kez çalıştırılan metotlara uygulanır. Temizlik işlemleri için kullanılır.
  • [IterationSetup]: Her iterasyondan önce çalıştırılan metotlara uygulanır.
  • [IterationCleanup]: Her iterasyondan sonra çalıştırılan metotlara uygulanır.
  • [Params]: Benchmark metotlarına parametre geçmek için kullanılır. Birden fazla parametre değeri ile benchmark’lar çalıştırılabilir.
[Params(100, 1000, 10000)]
public int N;

Gelişmiş Kullanım

BenchmarkDotNet, daha karmaşık senaryolar için çeşitli özellikler sunar. İşte bazı gelişmiş kullanım örnekleri:

Parametreli Benchmark

Farklı parametrelerle benchmark’lar çalıştırmak için [Params] özniteliği kullanılır:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

public class Benchmarks
{
    [Params(100, 1000, 10000)]
    public int N;

    private int[] numbers;

    [GlobalSetup]
    public void Setup()
    {
        numbers = Enumerable.Range(0, N).ToArray();
    }

    [Benchmark]
    public int SumWithForLoop()
    {
        int sum = 0;
        for (int i = 0; i < numbers.Length; i++)
        {
            sum += numbers[i];
        }
        return sum;
    }

    [Benchmark]
    public int SumWithLinq()
    {
        return numbers.Sum();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<Benchmarks>();
    }
}

Farklı Config Kullanımı

BenchmarkDotNet, benchmark’larınızı yapılandırmak için çeşitli seçenekler sunar. Özel bir yapılandırma kullanarak farklı ayarlarla benchmark çalıştırabilirsiniz:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;

public class Benchmarks
{
    private int[] numbers;

    [GlobalSetup]
    public void Setup()
    {
        numbers = Enumerable.Range(0, 1000).ToArray();
    }

    [Benchmark]
    public int SumWithForLoop()
    {
        int sum = 0;
        for (int i = 0; i < numbers.Length; i++)
        {
            sum += numbers[i];
        }
        return sum;
    }

    [Benchmark]
    public int SumWithLinq()
    {
        return numbers.Sum();
    }
}

public class CustomConfig : ManualConfig
{
    public CustomConfig()
    {
        AddColumn(BenchmarkDotNet.Columns.StatisticColumn.AllStatistics);
        AddExporter(BenchmarkDotNet.Exporters.MarkdownExporter.GitHub);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<Benchmarks>(new CustomConfig());
    }
}

Benchmark Sonuçlarının Analizi

BenchmarkDotNet, benchmark sonuçlarını detaylı bir şekilde analiz etmenizi sağlar. Çıktılar genellikle aşağıdaki formatlarda sunulur:

  • Mean: Ortalama süre.
  • Error: Hata payı.
  • StdDev: Standart sapma.
  • Min: En kısa süre.
  • Max: En uzun süre.

Bu metrikler, kodunuzun performansını değerlendirmenize ve iyileştirmenize yardımcı olur.

Özetle BenchmarkDotNet, .NET geliştiricileri için güçlü ve esnek bir performans ölçüm kütüphanesidir. Kurulumu ve kullanımı kolaydır ve çeşitli öznitelikler ile yapılandırılabilir. BenchmarkDotNet kullanarak, kodunuzun performansını detaylı bir şekilde ölçebilir, analiz edebilir ve iyileştirebilirsiniz. Performans testleri yazmak, uygulamalarınızın verimliliğini artırmak ve performans darboğazlarını tespit etmek için BenchmarkDotNet’i kullanabilirsiniz.


Çalıştırma

BenchmarkDotNet’ın düzgün çalışabilmesi için projenizi RELEASE modunda derlemeniz gerekiyor. Bu, optimizasyonların etkinleştirildiği ve daha doğru performans ölçümlerinin elde edilebileceği anlamına gelir. Aşağıdaki adımları izleyerek projenizi RELEASE modunda derleyebilirsiniz.

Adımlar

1. RELEASE Modunda Derleme

  1. Visual Studio kullanıyorsanız:
    • Menüden Build seçeneğine tıklayın.
    • Configuration Manager‘ı seçin.
    • Aktif çözüm yapılandırmasını Release olarak ayarlayın.
    • Projeyi derleyin (Build > Build Solution).
    • Projeyi çalıştırın (Debug > Start Without Debugging).
  2. .NET CLI kullanıyorsanız:
    • Projenizi RELEASE modunda derlemek ve çalıştırmak için aşağıdaki komutu çalıştırın:
dotnet build -c Release
dotnet run -c Release

Projenizin çalışması biraz uzun sürebilir çünkü BenchmarkDotNet, çalışırken çeşitli aşamalardan geçer: ölçüm öncesi ısınma (Warmup), ölçüm (Actual) ve temizlik (Cleanup). Bu, daha doğru sonuçlar elde etmek için yapılır. Ancak, sonuçları görmek için tüm aşamaların tamamlanmasını beklemeniz gerekiyor.

Elbette, BenchmarkDotNet çıktılarının değerlendirilmesi oldukça önemlidir. İşte örnek bir analiz:

MethodMeanErrorStdDev
EfCoreInsert2,157.07 us21.472 us19.035 us
DapperInsert1,955.13 us17.222 us16.110 us
EfCoreRead187.97 us4.397 us12.965 us
DapperRead63.75 us1.264 us1.812 us