BenchmarkDotNet, .NET uygulamalarımızda kodlarımızın performansını ölçebileceğimiz açık kaynak, lightweight bir kütüphanedir.
Bu kütüphane ile aynı işi yapan farklı kod parçalarını, metotları birbirine karşı kıyaslayabiliriz.
Neden benchmarking yapmalıyız?
- Projelerimizde kullanacağımız teknolojilere, alacağımız sonuçlarla karar verebiliriz.
- Kodlarda refactoring yapacağımız noktaları kolay kestirebiliriz.
- Performansın düşük olduğu kodlarda iyileştirmeler yapabiliriz.
- Alacağımız ölçüm metriklerine göre bellek yönetimini yapabiliriz.
Bu yazıda farklı senaryolarla kütüphane kullanımını anlatacağım.
Paketin, projeye dahil edilmesi
Install-Package BenchmarkDotNet
İlgili Nuget paketi: NuGet Gallery | BenchmarkDotNet
Örneğimde, farklı iki ORM aracı ile aynı sayıdaki ürün listesini getiren metotları karşılaştırıp, kütüphanenin özelliklerine değineceğiz. Dapper ve Entity Framework Core, karşılaştırılacak araçlardır.
Benchmark işlemi için bir sınıf oluşturduk. Sınıf içerisinde bütün ürünleri hem Dapper hem de Entity Framework Core ile listeleyecek metotların üzerinde Benchmark attribute işaretlendi.
Ayrıca listeleme metotlarının bulunduğu servislerin instance işlemleri Setup metodu ile tamamlanmış olup GlobalSetup attribute ile işaretlendi. GlobalSetup ile belirtilen metotta benchmark işleminden önce yapılacak işlemler, tanımlamalar belirtilir.
public class DapperEFCore { private IProductService _productServiceDapper; private IProductService _productServiceEFCore; private DapperProductDal dapper=new DapperProductDal(); private EfProductDal efCore = new EfProductDal(); [GlobalSetup] public void Setup() { _productServiceEFCore = new ProductManager(efCore); _productServiceDapper = new ProductManager(dapper); } [Benchmark(Description = "Benchmark for Dapper ORM")] public List<Product> DapperGetAllProducts() => _productServiceDapper.GetAll().Data; [Benchmark(Description = "Benchmark for Entitiy Framework Core")] public List<Product> EFCoreGetAllProducts() => _productServiceEFCore.GetAll().Data; }
Dapper ve EF Core ORM'lerinin kullanıldığı GetAll metotları aşağıdaki gibi belirtilmiştir.
//EF Core - Set metodu public List<TEntity> GetAll(Expression<Func<TEntity, bool>> filter = null) { using (var dbContext = new TContext()) { return filter == null ? dbContext.Set<TEntity>().ToList() : dbContext.Set<TEntity>().Where(filter).ToList(); } } //Dapper - Dapper.Contrib - GetAll metodu public List<TEntity> GetAll(Expression<Func<TEntity, bool>> filter = null) { using (var connection = DbConnect.Connection) { return filter == null ? connection.GetAll<TEntity>().ToList() : connection.GetAll<TEntity>().Where(filter.Compile()).ToList(); } }
public class Program { static void Main(string[] args) { var summary = BenchmarkRunner.Run<DapperEFCore>(); Console.ReadLine(); } }
Farklı bir senaryo olarak; ProductId değeri 20'den büyük olan ürünleri filtrelemek için parametreli metot kullanacağız ve id değerini parametre olarak geçeceğiz. Arguments attributesi, metoda parametre olarak gönderilecek değeri yazmamızı sağlar.
[Benchmark(Description = "Benchmark for Dapper ORM")] [Arguments(20)] public List<Product> DapperGetAllProducts(int productId) => _productServiceDapper.GetAll(x => x.ProductId > productId).Data; [Benchmark(Description = "Benchmark for Entitiy Framework Core")] [Arguments(20)] public List<Product> EFCoreGetAllProducts(int productId) => _productServiceEFCore.GetAll(x => x.ProductId > productId).Data;
[Params(1, 10, 25, 50)] public int productId; [Benchmark(Description = "Benchmark for Dapper ORM")] public List<Product> DapperGetAllProducts() => _productServiceDapper.GetAll(x => x.ProductId > productId).Data; [Benchmark(Description = "Benchmark for Entitiy Framework Core")]public List<Product> EFCoreGetAllProducts() => _productServiceEFCore.GetAll(x => x.ProductId > productId).Data;
Bellek yönetimi konusunda ölçüm yapabilmek adına aşağıdaki paketi de projemize dahil etmemiz gerekiyor.
Install-Package BenchmarkDotNet.Diagnostics.Windows
public class DapperEFCoreConfig : ManualConfig { public DapperEFCoreConfig() { AddDiagnoser(MemoryDiagnoser.Default); Add(DefaultConfig.Instance); } } [Config(typeof(DapperEFCoreConfig))] public class DapperEFCore { //piece of code }
public class Program { public static void Main(string[] args) { var config = new ManualConfig(); config.AddDiagnoser(MemoryDiagnoser.Default); config.Add(DefaultConfig.Instance); BenchmarkRunner.Run<DapperEFCore>(config); } }
Yorumlar
Yorum Gönder