.NET Core bir çok acıdan .NET teknolojileri ile geliştirilen sistemlere farklı yaklaşımlar katıyor. Açık kaynak geliştirme yaklaşımı, farklı platformlarda çalışabilen bir yapısının olması, performans açısından kuvvetli olması, hızlı ve sürekli olan geliştirme döngüleri gibi gibi temel bir kaç konu ve derinlerde niceleri… Bu yazıda çok derinlere inmeden, .NET Core’un performans konusundaki iyileştirmelerinden bir tanesinden bahsetmeye çalışacağım.

Şu sıralar bildiğiniz gibi .NET Core 2.2 Preview 2 yayınlandı ve RTM’e biraz daha yaklaştı. Bu versiyon ile arka tarafta oldukça önemli; performans ile alakalı, bir özellik .NET Core ile geliştirilen uygulamalara dahil oluyor. Performans tarafındaki bazı iyileştirmeler direkt geliştirme alışkanlıklarımıza dokunmasa da onların farkındalığı, uzun vadede önemli diye düşünüyorum.

Bahsedeceğim iyileştirme ya da yeni özellik, derleme tarafında olan bir yenilik. Ve aslında .NET Core 2.1 ile hayatımıza çoktan gelmişti. Ancak varsayılan özellik olarak bu özellik devreye sokulmamıştı. Sadece belli bir ayar ile aktif hale geliyordu. .NET Core 2.2 ile beraber artık varsayılan olarak, aktif bir şekilde .NET Core uygulamalarının hayatına girecek. .NET Core 2.2 Preview 2 ile de direkt artık aktif… Peki ne bu iyileştirme?

İyileştirmeden tam bahsetmeden önce, standart .NET Framework tarafındaki derleme yaklaşımını bir hatırlayalım. Bildiğiniz gibi yazmış olduğumuz C#/VB.NET/F# kodlarını derlediğimiz zaman, bu kodlar Microsoft Intermediate Language(MSIL)’e dönüşüyor ve *.dll olarak ya da *.exe olarak çalışmaya hazır bir şekilde saklanıyor. Kodlarımız çalıştığı zaman, Common Language Runtime(CLR) tarafından MSIL’e dönüşmüş kodlarımızı Just-In-Time(JIT) derleyicisi ile tekrar derleniyor ve işlemcinin(CPU) anlayacağı dile yani makine diline dönüştürüp işlemci tarafından çalıştırılmasını sağlıyor. Bu iki farklı derleme aşamasında, derleyiciler kendi çalışma durumlarına göre çeşitli optimizasyonlar yapıyor. Bu derlemeler tek bir seferde yapılıyor. Dolayısıyla yapılan optimizasyonlar tek bir seferlik oluyor. JIT derleyicisi çalışma zamanını direkt etkileyecek çıktılar ürettiği için oradaki optimizasyonlar oldukça önemli. Orada kullanılan algoritmalara göre derlenen çıktı, çok hızlı başlayabilir ama normal durağan anında farklı şekilde işleyebilir. Ya da tam tersi…Kısa bir özet olması için çok ayrıntılara girmiyor ve burada bırakıyorum, biz gelelim .NET Core 2.x tarafına…

.NET Core 2.1 ile, JIT tarafında bir çok iyileştirme yapıldı. Microsoft’un benchmark’larına göre de oldukça etkileyici çıktılara sahip iyileştirmeler. Bunlara buradan erişebilirsiniz…

.NET Core 2.2 ile hayatımıza girecek en önemli iyileştirme çalışma zamanında yapılan derlemenin tek değil, duruma göre çoklu versiyonlara sahip bir derleme olması. Bu sayede JIT derlemeyi birden fazla kez yapabilecek ve hızlı bir şekilde derlenmiş çıktı değişebilecek. Bu sayede de kodları daha hızlı çalışabilecek, hatta çalışıyor da. Bu olaya “Tiered Compilation” diyor .NET Core tarafı…

Biraz daha basite indirgeyip daha iyi anlayalım. Derlenmiş C# kodumuzun çıktısı MSIL, run-time zamanında JIT tarafından çok hızlı bir şekilde derleniyor(Tiered Compilation). Bu derleme aşamasında, kod çıktısı hızlı ayağa kalksın, motor hızlıca ısınsın(:P) diye belli optimizasyonlardan ferakat ediliyor. Eğer kod çok çalışan bir nokta ise derleme yine gerçekleşiyor ve farklı optimizasyonlar ile yine hızlı çalışan bir kod çıktısı oluyor.

Hepimizin bildiği; Release ve Debug modda derleyince farklı optimizasyonların yapılmış olmasını düşünün. Release modda derlendiğinde yapılan optimizasyonların uygulamanın çalışma şekline göre tekrar farklı farklı yapıldığını düşünün. Bu son “düşünün, düşünün” diye verdiğim örnek umarım biraz daha net anlaşılmasına yardımcı olur. 🙂

Başta da söylediğim gibi bu özellik, .NET Core 2.1 ile hayatımıza girmişti. Ancak *.csproj ya da environment değişkenlerinden aktif hale getirebiliyorduk. .NET Core 2.2 ile artık aktif hale getirmemize gerek yok. Varsayılan çalışma şekli olarak zaten aktif olacak. Ama benzer şekilde bu sefer de istersek, pasif hale almak mümkün olacak.

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
      <OutputType>Exe</OutputType>
      <TargetFramework>netcoreapp2.1</TargetFramework>
      <TieredCompilation>true(artık false yapıp kapatabiliriz)</TieredCompilation>
    </PropertyGroup>
</Project>

Arka taraftaki bu iyileştirme dediğim gibi geliştirme yaklaşımıza direkt dokunacak bir konu değil. Ama üzerinde çalıştığımız teknolojilerin, çalışma yapılarını ne kadar bilirsek, çözüm sağlama ve problem çözme yaklaşımlarımız o derece iyi olur düşüncesindeyim. Umarım bir şekilde de olsa faydası dokunur. Bir sonraki yazıda görüşmek üzere…