
.NET Ahead of Time (AOT), Just-in-time (JIT) ve Common Intermediate Language (CIL)
.NET Framework ve .NET Core, modern yazılım uygulamalarını geliştirmek için popüler platformlardır. Bu platformlar, uygulamaların çalıştırılmasını optimize etmek için iki ana derleme yaklaşımı kullanır: Ahead of Time (AOT) ve Just-in-time (JIT) derlemesi. Her iki yaklaşımın temel amacı, .NET kodunu işlemcinin anlayabileceği makine koduna dönüştürmektir. Bu makalede, AOT ve JIT derlemesi arasındaki ilişkiyi detaylı olarak açıklayacak ve her birinin nasıl çalıştığına dair örneklerle inceleyeceğiz.
Common Intermediate Language (CIL)
Common Intermediate Language (CIL), .NET platformunda çalışan dillerin ortak bir ara dilini temsil eden bir ara dil veya kod biçimidir. CIL, .NET uygulamalarının kaynak kodlarının derlendikten sonra ortaya çıkan yarı derlenmiş formudur.
CIL, .NET dilleri tarafından oluşturulan kodun hedef platforma bağımlı olmayan bir temsili olarak düşünülebilir. Örneğin, C# veya VB.NET gibi .NET dillerinde yazılan kodlar, derlendiklerinde CIL'ye dönüştürülür ve bu CIL, .NET platformunda çalışan sanal bir makine olan Common Language Runtime (CLR) tarafından çalıştırılır.
CIL'in bazı temel özellikleri şunlardır:
-
Platform Bağımsızlık: CIL, .NET platformunda çalışan sanal bir makine olan CLR tarafından yürütüldüğünden, CIL kodları, platform bağımsızdır. Bu, .NET uygulamalarının Windows, Linux, macOS gibi farklı işletim sistemlerinde çalışabilmesini sağlar.
-
Yüksek Seviye Dil Özellikleri: CIL, yüksek seviye programlama dillerine yakındır ve açıkça tanımlı bir yüksek seviye komut kümesini içerir. Bu sayede, CIL kodu daha anlaşılır ve okunabilir olur.
-
Stacked-Based Model: CIL, verileri yığın üzerinde işleyen bir yapıya sahiptir. Yani, işlem yapılacak değerler yığına konur ve işlemler yığından alınarak yapılır. Bu, CIL'in basit ve hızlı bir yürütme modeline sahip olmasını sağlar.
CIL kodu, .NET programlama dilleriyle oluşturulan kodun ortak bir ara diline dönüştürüldüğünden, farklı .NET dilleri arasında kolayca etkileşim sağlanabilir. Yani, C# ile yazılan bir uygulama, VB.NET ile yazılan bir bileşenle sorunsuz bir şekilde çalışabilir, çünkü her ikisi de aynı CIL dilini hedefler.
CIL'in çalıştırılması ise, ilgili .NET programlama dili tarafından CIL'in platforma özgü makine koduna (native code) dönüştürülmesi ve ardından CLR tarafından çalıştırılması ile gerçekleşir. Bu dönüşüm ve çalıştırma süreci sayesinde .NET uygulamaları, platform bağımsızlık ve uyumluluk sağlar.
Just-in-time (JIT)
Just-in-time (JIT) derlemesi, .NET uygulamalarının çalışma zamanında, kodun hedef makineye uygun olarak derlenmesi işlemidir. JIT derlemesi, uygulamanın çalıştırıldığı an itibarıyla, yani "runtime" sırasında gerçekleştirilir. Bu, uygulamanın herhangi bir platformda çalıştırılabilmesini ve yürütülebilir hale getirilmesini sağlar.
JIT derlemesi, .NET dilinden oluşturulan kodun Common Intermediate Language (CIL) adı verilen ara dilde oluşturulmasını içerir. Bu CIL kodu, platform bağımsızdır ve çalıştırılabilir durumda değildir. Uygulama çalıştırıldığında, JIT derleyici bu CIL kodunu platformun gerçek makine koduna dönüştürür ve işlemci tarafından doğrudan yürütülebilecek hale getirir. Bu sayede uygulama, çalıştırıldığı platformun özelliklerini tam olarak kullanabilir.
JIT Derlemesi Örneği
Aşağıdaki C# kodunu ele alalım:
using System;
public class Program
{
public static void Main()
{
int number1 = 10;
int number2 = 20;
int result = AddNumbers(number1, number2);
Console.WriteLine("Result: " + result);
}
public static int AddNumbers(int a, int b)
{
return a + b;
}
}
Yukarıdaki C# kodu, iki sayıyı toplayan basit bir .NET uygulamasını temsil eder. Bu kod derlenirken, CIL olarak adlandırılan ara dilde bir derleme oluşturulur.
Uygulama çalıştırıldığında, JIT derleyici bu CIL kodunu platformunun makine koduna dönüştürerek işlemcinin anlayabileceği bir hale getirir. Bu dönüştürme işlemi, uygulama çalıştırıldığında bir kez gerçekleşir ve daha sonra dönüştürülen makine kodu hafızada tutulur. Bu şekilde, uygulama daha sonra aynı kod parçacığını tekrar çağırırsa, makine kodunu kullanır ve JIT derlemesini tekrarlamaz.
Bu C# kodu, JIT derlemesi ile çalıştırıldığında aşağıdaki CIL koduna dönüştürülür:
.method public hidebysig static void Main() cil managed
{
.entrypoint
// Code size 23 (0x17)
.maxstack 2
.locals init (int32 V_0, //number1
int32 V_1, //number2
int32 V_2) //result
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: stloc.0
IL_0004: ldc.i4.s 20
IL_0006: stloc.1
IL_0007: ldloc.0
IL_0008: ldloc.1
IL_0009: call int32 Program::AddNumbers(int32, int32)
IL_000e: stloc.2
IL_000f: ldstr "Result: {0}"
IL_0014: ldloc.2
IL_0015: call void [mscorlib]System.Console::WriteLine(string, int32)
IL_001a: nop
IL_001b: ret
}
.method public hidebysig static int32 AddNumbers(int32 a, int32 b) cil managed
{
// Code size 7 (0x7)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: add
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: ret
}
Yukarıda gösterilen CIL kodu, JIT derlemesi ile çalıştırıldığında, platformun hedef makine koduna dönüştürülecektir. Ancak, JIT derlemesi işlemi gerçekleştirilmeden önce CIL kodu doğrudan makine koduna dönüştürebilecek bir AOT derleyici kullanılarak elde edilebilir. Bu durumda, örneğin CIL kodu bir x86 işlemci için x86 makine koduna dönüştürülecektir.
Sonuç olarak, makine kodu derleme zamanında gerçekleştirilen AOT derlemesi için platforma ve hedef işlemci mimarisine bağlı olarak değişecektir. JIT derlemesi, uygulamanın çalışma zamanında CIL kodunu platformun hedef makine koduna dönüştürerek çalıştırılabilir hale getirirken, AOT derlemesi, CIL kodunu çalıştırmadan önce doğrudan makine koduna dönüştürür ve uygulama çalıştırıldığında JIT derlemesine ihtiyaç duymaz.
Ahead of Time (AOT)
Ahead of Time (AOT) derlemesi ise, uygulamanın çalıştırılmadan önce, yani "build time" sırasında gerçekleştirilen bir derleme yaklaşımıdır. Bu yöntemde, CIL kodu derleme aşamasında doğrudan platformun makine koduna dönüştürülür. Böylece, uygulama çalıştırılmadan önce hedef platforma özel yürütülebilir bir dosya elde edilir.
AOT derlemesi, uygulamanın çalışma zamanında JIT derlemesi gerçekleştirmediği için performans açısından avantajlar sunabilir. Ayrıca, uygulamanın çalıştığı platformda JIT derlemesine gerek kalmaz, bu nedenle uygulama başlatma süresi azalır.
AOT ve JIT İlişkisi
AOT ve JIT derlemesi, .NET uygulamalarını çalıştırılabilir hale getirmek için farklı yaklaşımlar kullanırken, her ikisi de .NET Framework ve .NET Core'da yer alan ortak bir altyapıyı paylaşır. Hem JIT hem de AOT derlemesi, .NET platformunun esnekliğini ve platform bağımsızlığını korurken, performans ve başlatma süresi gibi farklı gereksinimleri karşılamak için kullanılabilir.
AOT derlemesi, özellikle yerel uygulama geliştirmek ve uygulama başlatma süresini minimize etmek isteyen durumlarda tercih edilir. JIT derlemesi ise, platform bağımsızlığı ve esneklik sağlama konusunda öne çıkar ve uygulama kodu çalıştırıldığında hedef platformun özelliklerine tam olarak uyarlanmasına olanak tanır.
.NET platformu, .NET Framework ve .NET Core aracılığıyla hem AOT hem de JIT derlemesi ile uygulama çalıştırma esnekliği sunar. AOT derlemesi, uygulama çalıştırılmadan önce platformun hedef makine koduna dönüştürülmesini sağlarken, JIT derlemesi uygulama çalıştırıldığında CIL kodunu platformun makine koduna dönüştürerek çalıştırılabilir hale getirir. Uygulama performansı ve başlatma süresi gibi gereksinimler göz önünde bulundurularak, geliştiriciler bu iki derleme yaklaşımından uygun olanı seçebilirler.
ASP.NET Core Web Host
ASP.NET Core Web Host, HTTP isteklerine yanıt vermek üzere tasarlanmış bir host türüdür. Bu host tipi, web uygulamalarının ve API'lerin çalıştırılması için idealdir. ASP.NET Core Web Host, Kestrel adı verilen ve varsayılan olarak entegre edilmiş hafif bir web sunucusu kullanır.
ASP.NET Core Web Host, IWebHost
arabirimi tarafından temsil edilir ve genellikle WebHostBuilder
sınıfıyla oluşturulur. Bu host tipi, HTTP isteklerini dinler, HTTP işleyicilerini çalıştırır ve web uygulamalarını çalıştırma görevlerini gerçekleştirir.
Örnek kullanım:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
Startup.cs
public class Startup
{
public Startup(IWebHostEnvironment env)
{
HostingEnvironment = env;
}
public IWebHostEnvironment HostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
if (HostingEnvironment.IsDevelopment())
{
// Development configuration
}
else
{
// Staging/Production configuration
}
var contentRootPath = HostingEnvironment.ContentRootPath;
}
}
Generic Host
Generic Host, .NET Core 3.0 ile tanıtılan ve ASP.NET Core Web Host'tan türetilen bir genel amaçlı host türüdür. Bu host tipi, web istemcileri, arka plan işlemleri, konsol uygulamaları ve diğer senaryolar için kullanılabilir. Generic Host, uygulamaların farklı hizmetlerin birleşimini çalıştırmasını sağlayan esnek bir yapı sunar.
Generic Host, IHost
arabirimi tarafından temsil edilir ve genellikle HostBuilder
sınıfıyla oluşturulur. Bu host tipi, .NET Core uygulamalarının başlatılmasını ve çalıştırılmasını sağlayan temel yapıyı sunar. Ayrıca, Dependency Injection (DI) ve Configuration gibi ortak görevleri yönetmek için kullanılır.
Örnek kullanım:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddTransient<MyService>();
})
.ConfigureHostConfiguration(config =>
{
// Host yapılandırması
})
.ConfigureAppConfiguration((hostContext, configBuilder) =>
{
// Uygulama yapılandırması
})
.ConfigureLogging((hostContext, loggingBuilder) =>
{
// Günlük yapılandırması
})
.ConfigureServices(services =>
{
services.AddHostedService<MyBackgroundService>();
});
public class MyService
{
public void DoWork()
{
Console.WriteLine("MyService is working!");
}
}
public class MyBackgroundService : IHostedService
{
private readonly MyService _myService;
public MyBackgroundService(MyService myService)
{
_myService = myService;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_myService.DoWork();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}
Web Application
Web Application, ASP.NET Core uygulamalarının tipik web projeleridir. Aşağıda, ASP.NET Core Web Application projelerinin nasıl oluşturulduğunu ve temel bir web uygulamasının nasıl yapılandırıldığını gösteren bir örnek bulunmaktadır:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
});
app.Run();
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
.NET Minimal API Nedir?
.NET Minimal API, .NET 6 ve sonraki sürümlerde sunulan, yazılım geliştiricilere hızlı ve basit bir şekilde API oluşturma imkanı sağlayan yeni bir yaklaşımdır. Geleneksel API geliştirme yöntemlerinde, ASP.NET gibi çeşitli katmanlar ve yapılar kullanılarak karmaşık ve hacimli API'ler oluşturulur. Bu durum, küçük çaplı projeler ve hızlı prototipleme süreçlerinde gereksiz karmaşıklık ve zaman kaybına yol açabilir. .NET Minimal API, bu tür senaryolarda daha hızlı ve basit API oluşturmayı amaçlayarak geliştiricilere kolaylık sağlar.
Minimal API'nin Avantajları
1. Azaltılmış Kod Miktarı
Geleneksel API'ler, yapılandırma dosyaları, kontroller ve genellikle birçok ek bileşeni içerir. Minimal API ile, API'leri oluşturmak için sadece temel yapıları kullanırız. Bu, kod miktarını azaltır ve daha okunabilir ve anlaşılır API'lere yol açar.
2. Basit ve Anlaşılır Sözdizimi
.NET Minimal API, basit ve açıklayıcı bir sözdizimine sahiptir. Bu, geliştiricilerin API'leri daha hızlı ve kolay bir şekilde oluşturmasını sağlar. Minimal API, daha az kodla aynı işlevselliği sunar ve daha az soyutlama ile çalışır.
3. Uyumluluk ve Geleceğe Dönük
.NET Minimal API, .NET 6'da sunulan bir özellik olarak başlamış olsa da, gelecekteki .NET sürümleriyle uyumludur ve desteklenmeye devam edecektir. Dolayısıyla, .NET geliştiricileri bu yeni yaklaşımı kullanarak geleceğe dönük uygulamalar oluşturabilir.
Minimal API Nasıl Oluşturulur?
.NET Minimal API, geleneksel ASP.NET Web API projesinden farklı bir yapıya sahiptir. Aşağıda, .NET Minimal API'nin nasıl oluşturulacağına dair temel adımlar yer almaktadır:
-
Öncelikle, .NET 6 veya sonraki bir sürümü içeren bir proje oluşturulmalıdır.
-
Minimal API için gereken bağımlılıklar projeye eklenmelidir. Bunun için gerekli paketler ve .NET CLI komutları kullanılabilir.
-
Projede Program.cs
dosyası oluşturulmalıdır. Bu dosya, Minimal API'nin temel yapılandırmasını ve işlevselliğini sağlar.
-
Program.cs
dosyasında, WebApplication
sınıfını kullanarak Minimal API'nin temel yapılandırmasını yapabiliriz. Geleneksel ASP.NET Web API'lerdeki karmaşık yapılar yerine, Minimal API daha basit bir şekilde yapılandırılır.
-
API rotaları, WebApplication
sınıfının üzerine MapMethods()
metodu ile eklenir. Bu şekilde API rotaları belirlenir ve ilgili HTTP metodlarına yönlendirilir.
-
Minimal API'nin diğer özelliklerini eklemek için kullanılacak sınıf ve metotlar tanımlanır.
-
API çalıştırılır ve test edilir. API, bir web sunucusuna dağıtılabilir veya yerel olarak çalıştırılabilir.
.NET Minimal API, .NET 6 ve sonraki sürümlerde sunulan yeni ve basit bir yaklaşımdır. Minimal API, yazılım geliştiricilere API oluşturmayı ve yönetmeyi kolaylaştırırken kod miktarını azaltır ve daha okunabilir bir yapı sunar. Gelecekte .NET platformunun önemli bir parçası olacak olan Minimal API, hızlı prototipleme ve küçük çaplı projeler için ideal bir seçenektir.
WebApplication.CreateBuilder()
ve WebApplication.CreateSlimBuilder()
metotları, .NET 6 ve sonraki sürümlerde sunulan Minimal API projesi için kullanılan iki farklı yöntemdir. Bu iki metot arasındaki temel farklar şunlardır:
1. WebApplication.CreateBuilder()
WebApplication.CreateBuilder()
metodu, .NET 6 ve sonraki sürümlerde Minimal API projeleri oluşturmak için kullanılan standart yöntemdir. Bu yöntem, bir IHostBuilder
örneği oluşturur ve Minimal API projesinin temel yapılandırmasını gerçekleştirir.
Bu yöntemin kullanılması, Minimal API projesinin klasik .NET uygulama bağımlılıkları ve hizmetlerini içeren tam özellikli bir proje oluşturmasını sağlar. Bu nedenle, daha kapsamlı projeler için tercih edilebilir. Özellikle, .NET Core uygulamalarından .NET 6'ya geçiş yaparken mevcut .NET Core projesinin Minimal API projesine dönüştürülmesi gerektiğinde bu yöntem kullanılabilir. Bu yöntem kullanılırsa, yüklenecek bazı kütüphaneler AOT özelliğini maalesef kullanamayacaktır.
Örnek kullanım:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Gerekli yapılandırmalar ve hizmetler eklenir.
// ...
var app = builder.Build();
app.Run();
2. WebApplication.CreateSlimBuilder()
WebApplication.CreateSlimBuilder()
metodu ise, Minimal API projesini daha küçük boyutlu ve hafif bir şekilde oluşturmak için kullanılan alternatif bir yöntemdir. Bu yöntem, CreateBuilder()
yönteminden farklı olarak Minimal API projesi oluştururken daha az varsayılan yapılandırmaya sahip bir IHostBuilder
örneği oluşturur.
Bu yöntemin kullanılması, Minimal API projeleri için yalnızca temel ihtiyaçlarının olduğu daha hafif uygulamalar oluşturmak için uygundur. Özellikle, küçük çaplı projeler veya hızlı prototipleme süreçleri ve AOT uyumluluk desteği için tercih edilebilir.
Örnek kullanım:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateSlimBuilder(args);
// Gerekli yapılandırmalar ve hizmetler eklenir.
// ...
var app = builder.Build();
app.Run();
Hangi Yöntemi Kullanmalı?
WebApplication.CreateBuilder()
yöntemi, daha kapsamlı projeler ve mevcut .NET Core projelerinin Minimal API projelerine geçiş süreci için daha uygundur. Bu yöntem, daha fazla yapılandırma seçeneği ve hizmeti içerir.
WebApplication.CreateSlimBuilder()
yöntemi ise, daha küçük boyutlu ve hafif Minimal API projeleri oluşturmak için tercih edilir. Özellikle, sadece temel ihtiyaçları olan ve daha az yapılandırma içeren projeler için uygundur.
Hangi yöntemin kullanılacağı, proje ihtiyaçlarına, boyutuna ve karmaşıklığına bağlıdır. Eğer proje kapsamlı ve büyükse CreateBuilder()
kullanılabilirken, küçük ve hafif bir proje için CreateSlimBuilder()
kullanmak daha uygun olacaktır.
Gününüz güzel geçsin.
Hoşçakalın.. 😎