BenchmarkDotNet ile Kıyaslama
BenchmarkDotNet ile doğru mikro kıyaslamalar yazın, aktarım hızını ve ayırmaları analiz edin, yaygın tuzaklardan kaçının.
BenchmarkDotNet ile Kıyaslama, CoddyKit'te ücretsiz bir C# Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C# Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C# Academy kursu toplamda 4 dersten oluşur.
Neden BenchmarkDotNet?
Mikro karşılaştırmalı test yapmak şaşırtıcı derecede zordur: JIT ısınması, GC duraklamaları, CPU önbellekleri ve işletim sistemi zamanlaması gürültüye neden olur. BenchmarkDotNet tüm bunları otomatik olarak yönetir ve istatistiksel olarak güvenilir sonuçlar üretir.
Kurulum ve İlk Karşılaştırmalı Test
NuGet paketini ekleyin, [Benchmark] yöntemlerine sahip bir sınıf oluşturun ve BenchmarkRunner.Run ile çalıştırın. Karşılaştırmalı testleri her zaman Release modunda çalıştırın.
// dotnet add package BenchmarkDotNet
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
[MemoryDiagnoser] // report allocations
[RankColumn] // rank methods by speed
public class StringBenchmarks
{
[Benchmark(Baseline = true)]
public string Concatenation()
{
var s = "";
for (int i = 0; i < 100; i++) s += i;
return s;
}
[Benchmark]
public string StringBuilder()
{
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 100; i++) sb.Append(i);
return sb.ToString();
}
}
// Program.cs (must run as Release):
BenchmarkRunner.Run<StringBenchmarks>();Sonuç Tablosunu Okuma
BenchmarkDotNet; ortalama süre, hata, standart sapma, oran ve bellek ayırmayı içeren bir sonuç tablosu yazdırır. Her sütunun nasıl yorumlanacağını burada bulabilirsiniz.
// Example output:
// | Method | Mean | Error | StdDev | Ratio | Alloc |
// |-------------- |---------:|--------:|--------:|------:|------:|
// | Concatenation | 4,210 ns | 81 ns | 76 ns | 1.00 | 6.4KB |
// | StringBuilder | 312 ns | 4 ns | 4 ns | 0.07 | 1.6KB |
// Mean: average time per operation
// Error: half of 99.9% confidence interval
// StdDev: standard deviation — high value = noisy environment
// Ratio: relative to Baseline=true method (1.00)
// Alloc: managed heap allocated per operation
// Rule of thumb:
// Error should be < 5% of Mean for reliable results
// Run on an isolated machine (no background tasks)Parametreli Karşılaştırmalı Testler
Bir karşılaştırmalı testi birden çok girdi boyutuyla çalıştırmak için [Params] kullanın. BenchmarkDotNet her birleşimi çalıştırır ve her parametre değeri için ayrı bir satır oluşturur.
[MemoryDiagnoser]
public class SearchBenchmarks
{
[Params(10, 100, 1000, 10000)]
public int N;
private int[] _data = Array.Empty<int>();
[GlobalSetup]
public void Setup()
=> _data = Enumerable.Range(0, N).ToArray();
[Benchmark]
public bool LinearSearch()
=> Array.IndexOf(_data, N - 1) >= 0;
[Benchmark]
public bool BinarySearch()
=> Array.BinarySearch(_data, N - 1) >= 0;
}Kurulum ve Temizleme
Tek seferlik kurulum veya yineleme başına kurulum/temizleme çalıştırmak için yaşam döngüsü özniteliklerini kullanın. Böylece kurulum maliyeti ölçülen karşılaştırmalı test süresinin dışında tutulur.
[MemoryDiagnoser]
public class DbQueryBenchmarks
{
private NpgsqlConnection _conn = null!;
private NpgsqlCommand _cmd = null!;
[GlobalSetup] // runs once before all benchmarks
public void Setup()
{
_conn = new NpgsqlConnection("...");
_conn.Open();
_cmd = new NpgsqlCommand("SELECT id FROM orders LIMIT 100", _conn);
}
[IterationSetup] // runs before EACH benchmark iteration
public void IterationSetup() { /* per-iteration prep */ }
[Benchmark]
public int QueryOrders() => (int)_cmd.ExecuteScalar()!;
[GlobalCleanup] // runs once after all benchmarks
public void Cleanup() { _cmd.Dispose(); _conn.Dispose(); }
}Bellek Tanılaması
[MemoryDiagnoser], işlem başına yönetilen yığın ayırmalarını raporlar. Karşılaştırmalı testler sırasında GC davranışını denetlemek için bunu [GcForce] seçenekleriyle birlikte kullanın.
[MemoryDiagnoser] // adds Alloc column to results
public class AllocationBenchmarks
{
[Benchmark]
public int[] AllocateArray() => new int[1000];
[Benchmark]
public Span<int> UseStackalloc()
{
Span<int> span = stackalloc int[1000];
return span; // WARN: for illustration; don't return stackalloc
}
[Benchmark]
public int[] ArrayPoolRent()
{
var arr = System.Buffers.ArrayPool<int>.Shared.Rent(1000);
System.Buffers.ArrayPool<int>.Shared.Return(arr);
return arr;
}
}Tanılayıcılar: ETW ve Disassembly
BenchmarkDotNet birden çok tanılayıcıyı destekler. DisassemblyDiagnoser, JIT optimizasyonlarını doğrulamak için ideal olan gerçek yerel derleme çıktısını gösterir.
using BenchmarkDotNet.Diagnosers;
[DisassemblyDiagnoser( // show generated ASM
maxDepth: 2,
printSource: true,
exportGithubMarkdown: true)]
[MemoryDiagnoser]
public class VectorizationBenchmarks
{
private float[] _data = new float[1024];
[Benchmark]
public float SumScalar()
{
float sum = 0;
foreach (var v in _data) sum += v;
return sum;
}
[Benchmark]
public float SumVectorized()
=> System.Numerics.Vector<float>.Count > 1
? VectorSum(_data)
: SumScalar();
}İş Yapılandırmaları
İşler, karşılaştırmalı test yürütme ortamını denetler: ısınma yinelemelerinin sayısı, yineleme başına çağrı sayısı, .NET çalışma zamanı sürümü ve JIT ayarları. Önceden tanımlanmış veya özel işler kullanın.
using BenchmarkDotNet.Jobs;
// Compare JIT vs Native AOT performance:
[SimpleJob(RuntimeMoniker.Net90)] // .NET 9 JIT
[SimpleJob(RuntimeMoniker.NativeAot90)] // .NET 9 AOT
[MemoryDiagnoser]
public class RuntimeComparison
{
[Benchmark]
public string SerializeJson()
{
var obj = new { Name = "Alice", Age = 30 };
return System.Text.Json.JsonSerializer.Serialize(obj);
}
}
// Custom job for more warmup:
[Config(typeof(MyConfig))]
public class PreciseBenchmarks
{
private class MyConfig : ManualConfig
{
public MyConfig()
=> AddJob(Job.Default.WithWarmupCount(5).WithIterationCount(20));
}
}Sonuçları Dışa Aktarma
BenchmarkDotNet sonuçları birden çok biçimde dışa aktarır: Markdown (GitHub PR'ları için), CSV (elektronik tablolar için), JSON ve HTML grafikleri. Dışa aktarma seçenekleri iş yapılandırmasında ayarlanır.
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Exporters.Csv;
[Config(typeof(ExportConfig))]
public class MyBenchmarks { /* ... */ }
public class ExportConfig : ManualConfig
{
public ExportConfig()
{
AddExporter(MarkdownExporter.GitHub);
AddExporter(CsvExporter.Default);
AddExporter(HtmlExporter.Default);
// Results in: BenchmarkDotNet.Artifacts/results/
}
}
// CLI usage to run specific benchmarks:
// dotnet run -c Release -- --filter "*StringBenchmarks*"
// dotnet run -c Release -- --list all (list all benchmarks)Gerçek Dünya: Optimizasyon Öncesi ve Sonrası
Bir performans optimizasyonunu doğrulamak için BenchmarkDotNet kullanma — basit, havuzlanmış ve Span tabanlı yaklaşımları karşılaştırma.
[MemoryDiagnoser]
[RankColumn]
public class ParsingBenchmarks
{
private const string Input = "2025-06-15T08:30:00Z";
[Benchmark(Baseline = true)]
public DateTime ParseViaString()
=> DateTime.Parse(Input);
[Benchmark]
public DateTime ParseExact()
=> DateTime.ParseExact(Input,
"yyyy-MM-ddTHH:mm:ssZ",
System.Globalization.CultureInfo.InvariantCulture);
[Benchmark]
public bool TryParse()
=> DateTime.TryParseExact(Input.AsSpan(),
"yyyy-MM-ddTHH:mm:ssZ",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out _);
}Hızlı Kontrol
BenchmarkDotNet karşılaştırmalı testleri neden dotnet run -c Release ile çalıştırılmalıdır?
Özet: BenchmarkDotNet ile Karşılaştırmalı Test
Temel çıkarımlar:
- NuGet aracılığıyla yükleyin; yöntemleri
[Benchmark]ile işaretleyin;dotnet run -c Releaseile çalıştırın [MemoryDiagnoser]: ayırma sütununu ekler;[RankColumn]: hıza göre sıralar[Params]: algoritmik karmaşıklığı bulmak için birden çok girdi boyutunda çalıştırır[GlobalSetup]/[GlobalCleanup]: ölçülen sürenin dışında tek seferlik kurulum[DisassemblyDiagnoser]: JIT optimizasyonlarını doğrulamak için oluşturulan yerel ASM'yi inceler- .NET 9 JIT ile Native AOT'yi veya farklı yineleme sayılarını karşılaştırmak için işleri kullanın
Sıkça Sorulan Sorular
“BenchmarkDotNet ile Kıyaslama” dersi ücretsiz mi?
Evet — “BenchmarkDotNet ile Kıyaslama” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C# Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C# Academy kursu toplamda 4 dersten oluşur.
“BenchmarkDotNet ile Kıyaslama” dersinde ne öğreneceğim?
BenchmarkDotNet ile doğru mikro kıyaslamalar yazın, aktarım hızını ve ayırmaları analiz edin, yaygın tuzaklardan kaçının. C# Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
C# Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te C# Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“BenchmarkDotNet ile Kıyaslama” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu C# Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her C# Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Native AOT Derlemesi
- Kırpma ve Yansıma Sınırlamaları
- ReadyToRun ve Katmanlı Derleme
- BenchmarkDotNet ile Kıyaslama