NET 11'de Runtime Async bellek tasarrufu nerede var, nerede yok
NET 11'deki Runtime Async, async/await'in durdurma mantığını derleyiciden çalışma zamanına taşıyor. Yazar, BenchmarkDotNet ile ölçümler yaparak tahsisat kazançlarını klasik modelle karşılaştırıyor. Kazancın hangi senaryolarda gerçek olduğu ve ölçüm yönteminin sonuçları nasıl değiştirdiği anlatılıyor.
Kilit noktalar
- Runtime Async .NET 11'de preview; csproj içinde <Features>$(Features);runtime-async=on</Features> ile açılır, <UseRuntimeAsync>false</UseRuntimeAsync> ile kapatılır.
- Senkron tamamlanan await zincirlerinde yazar BenchmarkDotNet ile 144 B'dan 0 B'a düşüş ölçtü; Task.Yield içeren zincirde ise 248 B'dan 168 B'a indi.
- Derin zincirde istisna fırlatıldığında tahsisat 84,2 KB'dan 5,71 KB'a düştü (sentetik test).
- Ölçümü tek süreçte mi yoksa ayrı süreçte mi yaptığınız sonucu değiştirebilir; karşılaştırmaları aynı yöntemle yapın.
- Stack trace'te async builder kareleri kayboldu; MoveNext veya <Method>d__0 adlarına bağlı loglama ve izleme kurallarını kontrol edin.
- DOTNET_RuntimeAsync ortam değişkeni artık desteklenmiyor; kapatma için UseRuntimeAsync kullanılmalı.
NET 11 önizlemesindeki Runtime Async özelliği, async metodların duraklatılmasını derleyicinin ürettiği durum makinelerinden alıp çalışma zamanına ve JIT'e bırakıyor. Yazar, RC2 sürümünde Microsoft'un yayımladığı tahsisat değerlerini kendi BenchmarkDotNet ölçümleriyle doğruladı. Senkron tamamlanan await zincirlerinde ara Task nesneleri oluşmadığı için tahsisat sıfıra iniyor, derin zincirlerde istisna maliyeti belirgin biçimde düşüyor ve derleme boyutu yarıya iniyor.
Ancak kazanç her senaryoda görülmüyor. Ölçümün tek süreçte mi yoksa ayrı süreçte mi yapıldığı sonucu tamamen değiştirebiliyor ve Task.Yield gibi gerçek duraklatmalarda klasik model bazı durumlarda daha az bellek kullanıyor. Özellik hâlâ önizlemede; csproj üzerinden Features ayarıyla açılıyor, eski ortam değişkenleri artık desteklenmiyor. async void, async iterator'lar ve özel task-like tipler şimdilik klasik yolda kalıyor.
Gerçek dünyada kullanımı
- Senkron sonuç dönen cache veya parser katmanlarında yüksek hacimli await zincirlerinde GC baskısını ölçmek.
- Hata yönetimi yoğun servislerde derin async çağrı zincirlerinde istisna maliyetini düşürmek.
- Büyük async kod tabanlı uygulamalarda derleme boyutunu ve dağıtım paketini küçültmek.
- Hata izleme ve loglama araçlarının async kare adlarına bağlı kurallarını yeni stack trace biçimine göre güncellemek.
Neden önemli
Runtime Async'i açmadan önce kendi iş yükünüzde, aynı ölçüm yöntemiyle, GC metrikleriyle birlikte test etmek gerekir. I/O bekleyen tipik API'lerde beklenen kazanç küçük; asıl fark sıcak yollardaki senkron tamamlanan await'lerde görülebilir.
Benzer haberler
- .NET 11 runtime async: await artık runtime tarafından yönetiliyorGérald Barré (Meziantou's blog)4 gün önce
- Jagged ve 2D dizilerde özel sıralama, LINQ ile karşılaştırmalı benchmarkC# Corner25 Eki
- .NET 11 Process.RunAndCaptureText ile stdout/stderr deadlock sorunu çözülüyorDEV Community: #csharp21 Eki