
Performans , herhangi bir web sitesinin başarısını düşünürken temel endişe kaynağıdır. Benzer görevleri yerine getiren binlerce web sitemiz var, ancak hepsi popüler değil. Bu binlerce web sitesi arasında, bazıları son derece optimize edilmiş veri, güvenlik ve iyi performansa sahip popülerdir. Her zaman en kısa sürede erişilebilen web sitelerini kullanmayı tercih ederiz.
Bir örnek verelim, Google, Bing, Baidu, Ask.com ve daha birçok arama motorumuz var. Ancak hepiniz biliyorsunuz, GOOGLE ve BING’i tercih ediyoruz , çünkü bunlara arama sonuçlarıyla 3–4 saniye içinde erişilebilir. Diyelim ki bunların sonucu aramak 10 saniyeden uzun sürüyorsa, sizce bunlarla devam ediyoruz. Ben öyle düşünmüyorum. Genellikle sonuçları beklemek istemiyoruz. Sonuçları her zaman çok zaman kaybetmeden en kısa sürede istiyoruz. Yani, yukarıdaki tartışmaya göre, performansın herhangi bir web sitesinin ana endişesi olduğunu söyleyebiliriz. Web siteniz iyi performans göstermiyorsa, minimum kullanıcı web sitenizle etkileşime girer.
Bugün, performansı artırmak için Asp.NET Core’da web sitesini geliştirirken uygulayabileceğimiz birkaç nokta öğreneceğiz .
Asp.Net Core, Microsoft tarafından oluşturulan ücretsiz, açık kaynaklı ve platformlar arası web geliştirme çerçevesidir. Asp.Net’te yükseltilmiş bir sürüm değildir, ancak Asp.Net MVC ve Asp.Net Web API’nin tek bir programlama modeli ile birlikte tamamen sıfırdan yeniden yazılmıştır.
Burada Asp.NET Core’un özelliklerini tartışmayacağım. Asp.NET Core’u anlamanıza yardımcı olacak en popüler makalelerin bazılarını takip edebilirsiniz . Asp.Net Core uygulamasının performans iyileştirmesi için ipuçlarına başlayalım.
- Asp.NET Core 2.0’ın 10 Yeni Özelliği
- Asp.Net Core MVC 2.0’daki ilk uygulama
- Asp.NET Core 2.0 Uygulamasını IIS’de Yayımlama
- Entity Framework Core ile Asp.NET Core Web API’sinde CRUD işlemleri
- EF Core ile Asp.NET Çekirdek MVC Kod İlk yaklaşım
- Çerez kullanarak Asp.NET Core MVC’de Kimlik Doğrulama ve Yetkilendirme
- Oracle veritabanı ve Dapper ile Asp.NET Core Web API
- Asp.NET Core 2.0’daki Razor Sayfaları
- Dapper ve Repository Pattern Asp.NET CORE 2.0 Razor Sayfalarında CRUD işlemleri
- .NET Framework’e karşı .Net Cor vs. Net Standart
1. HER ZAMAN ASP.NET CORE SON SÜRÜMÜNÜ KULLANIN
Asp.Net Core’un ilk sürümü Visual Studio 2015 ile 2016 yılında piyasaya sürüldü ve şimdi Asp.Net Core 2.2 sürümü mevcut. Performans geliştirmesini başlangıç sürümünden geçerli sürüme karşılaştırırsanız, Asp.Net Core 2.2’de (geçerli en son sürüm) geliştirilen uygulamanın önceki sürüme kıyasla çok hızlı çalıştığını göreceksiniz . Microsoft, önceki sürümle karşılaştırıldığında bir sonraki sürümde her zaman bazı performans iyileştirmeleri getirir.
Bu nedenle, uygulamayı Asp.Net Core kullanarak oluştururken, her zaman Asp.Net Core’un en son sürümünü kullanmayı tercih edin. En son sürümle, performans iyileştirmesini kesinlikle bulacaksınız. Asp.Net Core’un bir sonraki sürümü olan 3.0, geliştirilme aşamasındadır ve yakında Visual Studio 2019 ile piyasaya sürüleceğini ummaktadır.
2. HERHANGİ BİR DÜZEYDE EŞZAMANLI ÇAĞRIDAN KAÇININ
Asp.Net Core uygulamasını geliştirirken, engelleme çağrıları oluşturmaktan kaçının. Blocking call, tamamlanmaya kadar bir sonraki yürütmeyi engelleyen anlamına gelir. Aramayı engelleme veya Senkronize arama, API’den veri alıyor veya dahili olarak bazı işlemler gerçekleştiriyor olabilirsiniz. Aramayı her zaman asenkron bir şekilde yürütmelisiniz .
3. HER ZAMAN ASENKRON PROGRAMLAMA KULLANIN (ASYNC-AWAİT)
Asenkron programlama modeli C# 5.0’da tanıtıldı ve çok popüler oldu. Asp.Net Core, bir uygulamayı daha güvenilir, daha hızlı ve yanıt verebilir hale getirmek için aynı Asenkron Programlama paradigmasını kullanır.
Kodu yazarken uçtan uca Asenkron Programlama kullanmalısınız. Bir örnek verelim, veritabanı uygulaması olan bir Asp.Net Core MVC uygulamamız var. Bildiğimiz gibi, birçok ayrılık olabilir ve hepsi kullanıcı proje mimarisine bağlıdır, ancak Controller > Repository Katmanı vb.
[HttpGet]
[Route("GetPosts")]
public async Task<IActionResult> GetPosts()
{
try
{
var posts = await postRepository.GetPosts();
if (posts == null)
{
return NotFound();
}
return Ok(posts);
}
catch (Exception)
{
return BadRequest();
}
}
Depo düzeyinde asenkron programlamayı bu şekilde uygulayacağız.
public async Task<List<PostViewModel>> GetPosts()
{
if (db != null)
{
return await (from p in db.Post
from c in db.Category
where p.CategoryId == c.Id
select new PostViewModel
{
PostId = p.PostId,
Title = p.Title,
Description = p.Description,
CategoryId = p.CategoryId,
CategoryName = c.Name,
CreatedDate = p.CreatedDate
}).ToListAsync();
}
return null;
}
4. ASENKRON PROGRAMLAMA İLE GÖREV BEKLE VEYA TAT ET SONUCUNDAN KAÇININ
Asenkron Programlama ile çalışırken, Task.Wait ve Task.Result kullanmamanızı ve aşağıdaki nedenle await kullanmayı denemenizi öneririz.
- Bunlar görev tamamlanıncaya kadar iş parçacığını engeller ve görevin tamamlanmasını bekler. Task.Wait görev tamamlanıncaya kadar iş parçacığını eşzamanlı olarak engelleyin.
- Task.Wait ve Task.Result her ikisi de AggregateException içinde her türlü istisnayı sarar ve istisna işleme yaparken karmaşıklığı yaratır.Bunun yerine Task.Wait ve Task.Result ait bekliyor kullanırsanız o zaman istisna işleme konusunda endişe gerekmez.
- Bazen bu ikisi de geçerli iş parçacığını engeller ve DEADLOCKS durumu oluşturur.
- Paralel görev yürütme oluyor eğer Task.Wait ve Task.Result yalnızca kullanılabilir. Async programlama ile kullanmamanızı öneririz.
Aşağıdaki gibi en Task.Wait iyi ve kötü örnek anlayalım.
// Good Performance
Task task = DoWork();
await task;
// Bad Performance
Task task = DoWork();
task.Wait();
Aşağıdaki gibi en Task.Result iyi ve kötü örnek anlayalım.
// Good Performance on UI
Task<string> task = GetEmployeeName();
txtEmployeeName.Text = await task;
// Bad Performance on UI
Task<string> task = GetEmployeeName();
txtEmployeeName.Text = task.Result;
Asenkron Programlama için En İyi Uygulamalar hakkında daha fazla bilgi edinin .
5. G/Ç İŞLEMLERİNİ ASENKRON OLARAK YAPMA
G/Ç işlemlerini gerçekleştirirken, zaman uyumsuz diğer süreçleri etkilemeden bunu gerçekleştirmelidir. G/Ç işlemleri, dosya yükleme veya alma gibi bir dosyayla yürütme anlamına gelir . Resim yükleme, dosya yükleme veya başka bir şey olabilir. Senkronize bir şekilde gerçekleştirmeye çalışırsanız, ana iş parçacığını engeller ve G/Ç tamamlanıncaya kadar diğer arka plan yürütmesini durdurur. Bu nedenle, performans bakış açısına göre, G/Ç işlemleri için her zaman Asenkron yürütmeyi kullanmalısınız.
ReadAsync, WriteAsync, FlushAysnc vb.Gibi G / Ç işlemleri için birçok Async yöntemimiz var . Burada nasıl asenkron bir dosyanın bir kopyasını oluşturabilirsiniz basit bir örnek;
public async void CreateCopyOfFile()
{
string dir = @"c:\Mukesh\files\";
using (StreamReader objStreamReader= File.OpenText(dir + "test.txt"))
{
using (StreamWriter objStreamWriter= File.CreateText(dir+ "copy_test.txt"))
{
await CopyFileToTarget(objStreamReader, objStreamWriter);
}
}
}
public async Task CopyFileToTarget(StreamReader objStreamReader, StreamWriter objStreamWriter)
{
int num;
char[] buffer = new char[0x1000];
while ((num= await objStreamReader.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
await objStreamWriter.WriteAsync(buffer, 0, num);
}
}
6. HER ZAMAN ÖNBELLEK KULLAN
Sunucuya her seferinde istek sayısını azaltabilirsek, uygulamanın performansını artırabiliriz. Bu, sunucuya çağrı yapmayacağınız anlamına gelmez, sadece sunucuya HERHANGİ BİR çağrıyı yapmayacağınız anlamına gelir . İlk kez, sunucuya çağrı yapacak ve yanıtı alacaksınız ve bu yanıt bir süre için gelecek perspektif için bir yerde saklanacak (biraz zaman aşımı olacak) ve bir daha ki sefere aynı yanıt için çağrı yapacağınız zaman önce ilk istekte zaten veri varsa ve bir yerde sakladıysanız ve evet ise, sunucuya çağrı yapmak yerine depolanmış verileri kullanacağınızı kontrol edin.
Verileri sunucuya çağrı yapmadan sıkça alabileceğimiz bir yerde tutmak iyi bir uygulamadır. Burada Önbelleği kullanabiliriz. İçeriğin önbelleğe alınması sunucu çağrılarını tekrar tekrar azaltmamıza ve uygulamanın performansını artırmamıza yardımcı olur. Önbelleği, istemci tarafı önbellekleme, sunucu tarafı önbellekleme veya istemci / sunucu tarafı önbellekleme gibi bir konumun herhangi bir noktasında yapabiliriz.
Biz önbelleğe alma yapabiliriz gibi Asp.Net Çekirdek mevcut önbelleğe farklı türde sahip In-Memory veya kullanabileceğimiz Response caching ya da biz kullanabilirsiniz Distributed Caching. Asp.Net Core’da Caching hakkında daha fazla bilgi
public async Task<IActionResult> GetCacheData()
{
var cacheEntry = await
_cache.GetOrCreateAsync(CacheKeys.Entry, entry =>
{
entry.SlidingExpiration = TimeSpan.FromSeconds(120);
return Task.FromResult(DateTime.Now);
});
return View("Cache", cacheEntry);
}
7. VERİ ERİŞİMİNİ OPTİMİZE EDİN
Veri erişim mantığını optimize etmek için uygulamanın performansını da geliştirebiliriz . Hepimizin bildiği gibi, uygulamanın çoğu tamamen veritabanına bağımlı ve her zaman bir veritabanından veri almak zorundayız ve kullanıcı arayüzünde göstermeliyiz. Eğer durum bu ise uygulamanın daha zaman alıcı yüke çok zaman alacaktır . Burada, performansı daha iyi artırabilecek kodu yaparken uygulanabilecek birkaç teknik var.
- HTTP çağrılarının sayısını azaltın, her zaman ağ gidiş dönüşlerinin sayısını azaltmaya çalışmanız gerektiği anlamına gelir.
- Tüm verileri tek seferde almaya çalışın. Sunucuya birden çok çağrı yapmak yerine, gerekli tüm verileri getirebilecek bir veya iki çağrı yapın.
- Sıklıkla değiştirilmeyen verilerde önbelleği ayarlayın .
- Gerekli olmayan verileri önceden almaya çalışmayın , yanıt üzerindeki yükü artıracak ve uygulamanız daha yavaş yüklenecektir.
8. ÖZEL KODU OPTİMİZE EDİN
Veri erişim mantığını optimize etmenin yanı sıra, business logic veya middlewareyazılımı özel kodunu da optimize edebiliriz . Bu kodları optimize etmek veya yeniden düzenlemek, uygulamaların performansını artırmamıza yardımcı olur. Burada odaklanmamız gereken bazı noktalar var.
- Loglama, Authentication veya her istekte çalışan bazı özel işleyici kodları optimize edilmelidir.
- Business logic layer veya middleware yazılımında özel uzun süreli özel yürütme gerçekleştirmeyin, temel olarak sunucuya gitme isteğini engeller ve uygulamanın verileri alması çok zaman alır. Bunun için, istemci tarafında veya veritabanı tarafında optimize edilmiş bir kodunuz olmalıdır.
- Her zaman uzun süren bir görevin, diğer işlemleri etkilemeden asenkron olarak gerçekleştirilmesi gerektiğini kontrol edin .
- Asenkron olarak çalışan SignalR olarak gerçek zamanlı istemci-sunucu iletişim örneği alabilirsiniz.
9. ENTITY FRAMEWORK CORE SORGU OPTİMİZASYONU
Hepimizin bildiği gibi, EF Core bir ORM’dir . Her zamanki gibi çok kod yazmadan veritabanı nesnesiyle oynamamıza yardımcı olan net geliştiriciler. Modeller kullanarak bir veritabanı kullanmamıza yardımcı olur. Veri erişim mantık kodu performanslarda hayati bir rol oynayabilir. Kodunuz uygulamanızdan daha iyi optimize edilmediyse uygulamanız iyi performans göstermez.
Ancak veri erişim mantığınızı EF Core’da en iyi şekilde yazarsanız, uygulamanın performansını kesinlikle artırır. Burada performansı artıracak bazı tekniklerimiz var.
- Sadece okuma amaçlı veri alırken ‘No Tracking’. Performansı artırır.
- Veritabanı tarafında verileri filtrelemeye çalışın, sorguyu kullanarak tüm verileri getirmeyin ve sonunda filtreleyin. EF Çekirdeğinde , veritabanı tarafında verileri filtrelemenize yardımcı olan Where, Select vb. Gibi bazı işlevleri kullanabilirsiniz .
- Take ve Skip işlevini kullanarak gereken tek kayıt sayısını alın . Sayfa numarasını tıklarken Take and Skip‘yı uygulayabileceğiniz bir sayfalama örneği alabilirsiniz.
Bir örnek alalım ve Select ve AsNoTracking kullanarak EF Core sorgusunu nasıl optimize edebileceğimizi anlamaya çalışalım.
public async Task<PaginatedList<Post>> GetPagedPendingPosts(int pageIndex, int pageSize, List<Category> allowedCategories)
{
var allowedCatIds = allowedCategories.Select(x => x.Id);
var query = _context.Post
.Include(x => x.Topic.Category)
.Include(x => x.User)
.Where(x => x.Pending == true && allowedCatIds.Contains(x.Topic.Category.Id))
.OrderBy(x => x.DateCreated);
return await PaginatedList<Post>.CreateAsync(query.AsNoTracking(), pageIndex, pageSize);
}
10. DİĞER BAZI İPUÇLARI
Burada Asp.Net Core uygulamasında uygulanabilecek bazı performans iyileştirme şeylerimiz var.
- Optimize edilmiş ve test edilmiş ve istisnanın akışın bir parçası olmasını en aza indiren işlem için mantığı yazın . İstisna kodunu yürütme şansının az olması, yüksek performans gösteren uygulama anlamına gelir.
- Veritabanı işlemleri için her zaman basit ADO.NET kodu veya Dapper gibi yüksek performanslı ORM kullanmaya çalışın . Bunun nedeni, veritabanı işlemlerinin sorguyu yürütmek için çok zaman alması durumunda uygulamanın performansını düşürmesidir. Hepimizin bildiği gibi, geliştirme aşamasında, ADO.NET kodunu uygulamak ve yönetmek, ORM uygulamasına kıyasla daha fazla zaman alacaktır. Ancak, basit bir ADO.NET kullanıyorsanız, uygulamanız başka bir ORM kullanmanızdan daha hızlı olacaktır.
- Yanıt boyutu açık olandan büyükse, yüklenmesi çok zaman alacaktır. Bu nedenle, sıkıştırma tekniklerini kullanarak yanıt boyutunu her zaman azaltın ve ardından verileri yükleyin. Sıkıştırma mantığını ara katman yazılımına uygulayabilirsiniz. Gzip, Brotli vb. gibi sıkıştırma sağlayıcıları bazılarını kullanabiliriz.
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Fastest;
});
}
BONUS İPUÇLARI (MÜŞTERİ TARAFI)
İstemci tarafı kodu için bazı performans ipuçlarını paylaşmak istiyoruz . Asp.Net Core MVC kullanarak bir web sitesi oluşturuyorsanız, o zaman inanıyorum, web sitenizin iyi performans göstermesi için her zaman bu ipuçlarını izlemelisiniz.
- Paketleme ve Küçültme: Bu paketleme ve küçültmeyi kullanarak kullanıcı arayüzüne yüklemeden önce içeriği optimize edebiliriz. Performans bakış açısına göre, JS / CSS gibi tüm müşteri tarafı varlıklarınızı her zaman tek seferde yüklemeye çalışın. Ağ isabetlerinin sayısını azaltır. Önce minyatür kullanarak dosyalarınızı küçültebilir ve daha sonra daha hızlı yüklenebilecek ve kaynaklar için bir HTTP isteği sayısını azaltabilecek bir dosyada paketleyebilirsiniz.
- JavaScript’i Sonra Yükle: Her zaman en sonunda JavaScript dosyalarınızı yüklemeyi denemelisiniz. Öncelikle web sitenizin minimum sürede oluşturulması ve JavaScript’inizin ne zaman yürütüleceği gibi DOM öğeleriniz kullanılabilir olacaktır. Bunu kullanarak uygulamanızı daha hızlı hale getirebilirsiniz.
- Görüntüleri Küçült: Görüntüleri her zaman maksimum boyutta yüklemekten kaçının. Yüklemeden önce, sıkıştırma tekniklerini kullanarak görüntüleri küçültebilirsiniz.
- CDN kullan: Özel CSS veya JavaScript dosyalarınız varsa, onu yüklemek sorun olmaz. Ancak, CDN sürümü olan bazı üçüncü taraf kitaplıkları kullanıyorsanız, her zaman CDN dosya yolunu sonuna kadar indirmektense CDN dosya yolunu kullanmayı deneyin.
Sonuç
Bugün bir Asp.Net Core uygulamasının performansını nasıl geliştireceğimizi öğrendik.
Umarım bu yazı size yardımcı olacaktır.