Performans Neden Bu Kadar Kritik?
Bir mobil uygulamanın başarısını belirleyen tek şey özellik listesi değil. Kullanıcıya sunduğunuz deneyimin ne kadar hızlı ve akıcı olduğu, çoğu zaman özelliklerden bile daha belirleyici. Google'ın araştırmalarına göre, başlatılma süresi 3 saniyeyi aşan uygulamalarda kullanıcıların %53'ü doğrudan uygulamayı terk ediyor. Düşünün — geliştirmeye aylar harcadığınız bir uygulamayı, kullanıcı daha görmeden kapatıyor.
.NET MAUI, .NET 10 ve yaklaşan .NET 11 ile performans tarafında ciddi mesafe katetti. XAML kaynak üreteci (source generator), yeni CollectionView handler'ları, NativeAOT desteği, tam trimming... Framework olgunlaşıyor, bu kesin. Ama şunu da kabul etmek lazım: framework ne kadar optimize olursa olsun, uygulama seviyesindeki kararlar hâlâ geliştiricinin omuzlarında.
Bu rehberde başlangıç süresinden CollectionView performansına, bellek yönetiminden profilleme araçlarına kadar her şeyi çalışan kod örnekleriyle ele alacağız. Haydi başlayalım.
Başlangıç Süresi Optimizasyonu
İlk izlenim her şeydir. Kullanıcı uygulamayı açtığı andan ilk ekranı gördüğü ana kadar geçen süre, tüm deneyimin tonunu belirler.
İşte bu süreyi minimuma indirmek için uygulamanız gereken stratejiler.
AOT ve NativeAOT ile Derleme Stratejileri
.NET MAUI uygulamalarında varsayılan çalışma zamanı Mono'dur ve JIT (Just-in-Time) derleme kullanır. Yani her C# metodu ilk çağrıldığında yerel koda derleniyor — bu da başlangıç performansını doğrudan vuruyor.
Profiled AOT (Startup Tracing), Release yapılarında zaten varsayılan olarak etkin. Başlatma yolundaki kritik metotları önceden derleyerek başlangıç süresini gözle görülür şekilde iyileştirir:
<!-- .csproj dosyasında Profiled AOT yapılandırması -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<!-- Android için varsayılan olarak etkindir -->
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
<!-- Özel AOT profili kullanmak isterseniz -->
<AndroidUseDefaultAotProfile>false</AndroidUseDefaultAotProfile>
</PropertyGroup>
NativeAOT ise işleri bir üst seviyeye taşıyor. .NET 8'den itibaren iOS, MacCatalyst ve Windows'ta kullanılabilen bu seçenek, Mono'ya kıyasla %50 daha küçük uygulama boyutu ve yaklaşık 2 kat daha hızlı başlangıç süresi sunuyor:
<!-- iOS/MacCatalyst için NativeAOT etkinleştirme -->
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PublishAot>true</PublishAot>
<!-- NativeAOT ile uyumsuz kodları tespit etmek için -->
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
Dikkat: NativeAOT henüz Android'de desteklenmiyor. Android tarafında Profiled AOT hâlâ en iyi seçenek. Bir diğer önemli nokta: NativeAOT, dotnet-trace profilleme aracıyla çalışmıyor. Performans analizi için Mono çalışma zamanı veya Xcode Instruments gibi yerel araçlara yönelmeniz gerekecek.
Trimming ile Uygulama Boyutunu Küçültme
Trimming, .NET IL Linker kullanarak kullanılmayan kodu uygulamadan temizler. .NET 10'la birlikte tam trimming desteği çok daha güvenilir hale geldi:
<PropertyGroup>
<!-- Tam trimming modunu etkinleştir -->
<TrimMode>full</TrimMode>
<!-- Trimming uyarılarını göster -->
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<!-- Reflection tabanlı kodu tespit et -->
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>
Burada bir uyarı vermek isterim: trimming etkinleştirildiğinde Reflection kullanan kodlar çalışma zamanında hata verebilir. [DynamicallyAccessedMembers] ve [RequiresUnreferencedCode] niteliklerini doğru kullanmak şart.
Shell Navigation ile Tembel Sayfa Yükleme
Shell tabanlı navigasyon, sayfaları isteğe bağlı (on-demand) oluşturur. Tüm sayfaları uygulama açılırken yüklemek yerine, sadece kullanıcı o sayfaya gittiğinde oluşturulur. Basit ama etkili bir yaklaşım:
// AppShell.xaml.cs
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
// Rota tabanlı navigasyon - sayfa yalnızca
// bu rotaya gidildiğinde oluşturulur
Routing.RegisterRoute("detay", typeof(DetayPage));
Routing.RegisterRoute("ayarlar", typeof(AyarlarPage));
Routing.RegisterRoute("profil", typeof(ProfilPage));
}
}
Dependency Injection Optimizasyonu
DI konteyneri üzerindeki tür kayıtları başlatma süresini doğrudan etkiler. Bunu çoğu geliştirici gözden kaçırıyor açıkçası. Transient yerine mümkün olduğunca Singleton veya Scoped kullanın ve ağır servisleri Lazy<T> ile sarmalayın:
// MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
// Sık kullanılan servisleri Singleton olarak kaydedin
builder.Services.AddSingleton<IApiService, ApiService>();
builder.Services.AddSingleton<IVeritabaniServisi, VeritabaniServisi>();
// Ağır servisleri Lazy ile sarın
builder.Services.AddSingleton<Lazy<IRaporlamaServisi>>(sp =>
new Lazy<IRaporlamaServisi>(() =>
sp.GetRequiredService<IRaporlamaServisi>()));
// Sayfa ve ViewModel kayıtları - Transient
builder.Services.AddTransient<AnaSayfaViewModel>();
builder.Services.AddTransient<AnaSayfa>();
return builder.Build();
}
}
Asenkron Başlatma Deseni
Başlatma sırasında ağır işlemleri asenkron olarak erteleyin. Veritabanı bağlantıları, API çağrıları, dosya okuma... Bunların hepsini ana thread'den ayırabilirsiniz:
// App.xaml.cs
public partial class App : Application
{
public App()
{
InitializeComponent();
}
protected override Window CreateWindow(IActivationState? activationState)
{
// Kritik olmayan başlatma görevlerini erteleme
Task.Run(async () =>
{
await BaslatmaGorevleri.OnbellekIsitAsync();
await BaslatmaGorevleri.AnalitikBaslatAsync();
});
return new Window(new AppShell());
}
}
// Tembel görev deseni
public static class BaslatmaGorevleri
{
private static readonly Lazy<Task> _onbellekGorevi =
new(() => OnbellekIsitCoreAsync());
public static Task OnbellekIsitAsync() => _onbellekGorevi.Value;
private static async Task OnbellekIsitCoreAsync()
{
// Önbelleği ısıt - UI'yi bloklamaz
await Task.Delay(100);
// Veritabanı sorgularını çalıştır...
}
public static async Task AnalitikBaslatAsync()
{
// Analitik SDK'yı başlat - kullanıcıyı bekletmez
await Task.Delay(50);
}
}
CollectionView Performans Optimizasyonu
CollectionView, .NET MAUI'nin en çok kullanılan kontrolü. Ama aynı zamanda performans sorunlarının da en sık yaşandığı yer burası. Büyük veri setlerinde akıcı kaydırma sağlamak, birkaç temel tekniği bilmeyi gerektiriyor.
Sanallaştırmayı (Virtualization) Koruyun
CollectionView'ın süper gücü UI sanallaştırması. Sadece ekranda görünen öğeler için yerel kontrol oluşturuluyor, gerisine dokunulmuyor. Ama bu mekanizmayı yanlış kullanımla kolayca bozabilirsiniz.
En kritik hata: CollectionView'ı bir ScrollView içine koymak. Bu, sanallaştırmayı tamamen öldürür. Tüm öğeler aynı anda render edilir. 10.000 satırlık bir listede bu, %94'e varan performans kaybı demek. Evet, yüzde doksan dört.
<!-- ❌ YANLIŞ: ScrollView sanallaştırmayı devre dışı bırakır -->
<ScrollView>
<VerticalStackLayout>
<Label Text="Başlık" />
<CollectionView ItemsSource="{Binding Urunler}" />
</VerticalStackLayout>
</ScrollView>
<!-- ✅ DOĞRU: Grid ile yıldız boyutlandırma kullanın -->
<Grid RowDefinitions="Auto,*">
<Label Text="Başlık" Grid.Row="0" />
<CollectionView
ItemsSource="{Binding Urunler}"
Grid.Row="1" />
</Grid>
ItemSizingStrategy ile Layout Hesaplamalarını Azaltma
Varsayılan olarak CollectionView her öğeyi ayrı ayrı ölçer. Eğer öğeleriniz aynı boyuttaysa (ki çoğu listede öyledir), MeasureFirstItem stratejisiyle gereksiz ölçümleri atlayabilirsiniz:
<CollectionView
ItemsSource="{Binding Urunler}"
ItemSizingStrategy="MeasureFirstItem">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Urun">
<!-- Sabit yükseklikli öğe şablonu -->
<Grid HeightRequest="80" Padding="12"
ColumnDefinitions="60,*,Auto">
<Image Source="{Binding ResimUrl}"
WidthRequest="60" HeightRequest="60" />
<Label Text="{Binding Ad}"
Grid.Column="1"
VerticalOptions="Center" />
<Label Text="{Binding Fiyat, StringFormat='{0:C}'}"
Grid.Column="2"
VerticalOptions="Center" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Compiled Bindings ile Veri Bağlama Hızını Artırma
Varsayılan bağlamalar Reflection kullanır ve bu pahalı bir işlem. Compiled bindings ise bağlama ifadelerini derleme zamanında çözer — klasik bağlamalara göre 8-20 kat daha hızlı. Tek yapmanız gereken x:DataType niteliğini eklemek:
<!-- ContentPage seviyesinde veri türünü belirtin -->
<ContentPage
xmlns:viewmodel="clr-namespace:UygulamaAdi.ViewModels"
x:DataType="viewmodel:UrunListeViewModel">
<CollectionView ItemsSource="{Binding Urunler}">
<CollectionView.ItemTemplate>
<!-- DataTemplate seviyesinde model türünü belirtin -->
<DataTemplate x:DataType="model:Urun">
<Grid Padding="8">
<!-- Compiled binding: Reflection yok, derleme zamanında çözülür -->
<Label Text="{Binding Ad}" FontSize="16" />
<!-- Salt okunur veriler için OneTime modunu kullanın -->
<Label Text="{Binding Aciklama, Mode=OneTime}"
FontSize="12" TextColor="Gray" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
Sonsuz Kaydırma (Infinite Scrolling) ile Büyük Veri Setleri
Binlerce öğeyi tek seferde yüklemek yerine sayfalama kullanın. Bu hem bellek hem de başlangıç süresi açısından büyük fark yaratır:
public class UrunListeViewModel : ObservableObject
{
private readonly IApiService _apiService;
private int _sayfaNumarasi = 0;
private const int SayfaBoyutu = 20;
private bool _yukleniyor = false;
public ObservableCollection<Urun> Urunler { get; } = new();
public UrunListeViewModel(IApiService apiService)
{
_apiService = apiService;
// İlk sayfayı yükle
DahaFazlaYukleCommand = new AsyncRelayCommand(DahaFazlaYukleAsync);
}
public IAsyncRelayCommand DahaFazlaYukleCommand { get; }
private async Task DahaFazlaYukleAsync()
{
if (_yukleniyor) return;
_yukleniyor = true;
try
{
var yeniUrunler = await _apiService
.UrunleriGetirAsync(_sayfaNumarasi, SayfaBoyutu);
foreach (var urun in yeniUrunler)
{
Urunler.Add(urun);
}
_sayfaNumarasi++;
}
finally
{
_yukleniyor = false;
}
}
}
<!-- XAML'de RemainingItemsThreshold kullanarak otomatik yükleme -->
<CollectionView
ItemsSource="{Binding Urunler}"
RemainingItemsThreshold="5"
RemainingItemsThresholdReachedCommand="{Binding DahaFazlaYukleCommand}"
ItemSizingStrategy="MeasureFirstItem">
<!-- ItemTemplate -->
</CollectionView>
Bellek Yönetimi ve Sızıntı Önleme
Mobil cihazlarda bellek kısıtlı ve yönetilmeyen bellek sızıntıları uygulamanızın çökmesine (veya daha kötüsü, işletim sistemi tarafından sessizce sonlandırılmasına) yol açabilir. Kendi projelerimde en çok karşılaştığım sızıntı kaynakları: olay işleyicileri ve dispose edilmeyen kaynaklar.
Olay İşleyici Temizliği
Bir sayfadan ayrılırken olay aboneliklerini temizlememek, o sayfanın çöp toplayıcı tarafından toplanmasını engeller. Klasik bir bellek sızıntısı senaryosu:
public partial class DetaySayfa : ContentPage
{
private readonly SensorService _sensor;
public DetaySayfa(SensorService sensor)
{
InitializeComponent();
_sensor = sensor;
}
protected override void OnAppearing()
{
base.OnAppearing();
// Olay aboneliği ekle
_sensor.VeriGeldi += Sensor_VeriGeldi;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
// Olay aboneliğini kaldır - bellek sızıntısını önler
_sensor.VeriGeldi -= Sensor_VeriGeldi;
}
private void Sensor_VeriGeldi(object? sender, SensorVeriEventArgs e)
{
// Sensör verisini işle
MainThread.BeginInvokeOnMainThread(() =>
{
DegerLabel.Text = e.Deger.ToString("F2");
});
}
}
WeakEventManager Kullanımı
Her seferinde manuel olarak event subscribe/unsubscribe yapmak zahmetli olabiliyor. WeakEventManager zayıf referanslar kullanarak bu sorunu otomatik çözer:
public class BildirimServisi
{
private readonly WeakEventManager _eventManager = new();
public event EventHandler<BildirimEventArgs> BildirimGeldi
{
add => _eventManager.AddEventHandler(value);
remove => _eventManager.RemoveEventHandler(value);
}
public void BildirimGonder(string mesaj)
{
_eventManager.HandleEvent(
this,
new BildirimEventArgs(mesaj),
nameof(BildirimGeldi));
}
}
Bellek Profilleme ile Sızıntı Tespiti
dotnet-gcdump aracı, uygulamanızın bellekteki tüm yönetilen nesnelerinin anlık görüntüsünü alır:
# dotnet-gcdump kurulumu
dotnet tool install -g dotnet-gcdump
# Çalışan uygulamadan bellek dökümü al
dotnet-gcdump collect -p <process-id>
# Visual Studio veya PerfView ile .gcdump dosyasını analiz et
Bir de topluluk tarafından geliştirilen MemoryToolkit.Maui var. .NET MAUI'ye özel bellek sızıntılarını otomatik tespit etmek için oldukça kullanışlı bir araç, mutlaka göz atın.
UI Rendering Performansı
Arayüzün akıcılığı, doğru layout seçimleri ve render optimizasyonlarıyla doğrudan bağlantılı. Yanlış layout kararları her karede gereksiz hesaplamalara ve o sinir bozucu görsel takılmalara yol açar.
Layout İç İçe Geçirme Derinliğini Azaltma
Derin iç içe geçmiş layout'lar, her frame'de tüm ağacın yeniden hesaplanmasına neden olur. Çözüm basit: mümkün olduğunca düz bir hiyerarşi kurun.
<!-- ❌ YANLIŞ: 4 seviye iç içe layout -->
<VerticalStackLayout>
<HorizontalStackLayout>
<VerticalStackLayout>
<HorizontalStackLayout>
<Image Source="profil.png" />
<Label Text="{Binding Ad}" />
</HorizontalStackLayout>
<Label Text="{Binding Aciklama}" />
</VerticalStackLayout>
<Label Text="{Binding Tarih}" />
</HorizontalStackLayout>
</VerticalStackLayout>
<!-- ✅ DOĞRU: Tek seviye Grid ile aynı sonuç -->
<Grid ColumnDefinitions="48,*,Auto"
RowDefinitions="Auto,Auto"
Padding="8" ColumnSpacing="8">
<Image Source="profil.png"
Grid.RowSpan="2"
WidthRequest="48" HeightRequest="48" />
<Label Text="{Binding Ad}"
Grid.Column="1" Grid.Row="0"
FontAttributes="Bold" />
<Label Text="{Binding Aciklama}"
Grid.Column="1" Grid.Row="1"
TextColor="Gray" />
<Label Text="{Binding Tarih}"
Grid.Column="2" Grid.Row="0"
FontSize="12" />
</Grid>
Görsel Kaynak Optimizasyonu
Görseller hem uygulama boyutunu hem de bellek tüketimini doğrudan etkiler. Şu stratejileri uygulayın:
- SVG kullanın: Vektörel grafikler her çözünürlükte net görünür ve dosya boyutu çok daha küçüktür.
- WebP formatını tercih edin: PNG'ye göre %25-34 daha küçük dosya boyutu.
- Uygun boyutlandırma: 50x50 piksel alanda gösterilecek bir görsel için 2000x2000 piksellik dosya yüklemeyin (buna şaşıracak kadar sık rastlıyorum).
- Önbellek kullanın: Ağdan indirilen görseller için .NET MAUI'nin yerleşik önbellek mekanizmasını aktif edin.
<!-- Görsel önbellekleme ve boyutlandırma -->
<Image Source="{Binding ProfilResimUrl}"
WidthRequest="48"
HeightRequest="48"
Aspect="AspectFill">
<Image.Source>
<UriImageSource
Uri="{Binding ProfilResimUrl}"
CacheValidity="7:00:00:00"
CachingEnabled="True" />
</Image.Source>
</Image>
.NET 10 ve .NET 11 ile Gelen Performans İyileştirmeleri
.NET 10 ve yaklaşan .NET 11, performans tarafında gerçekten güzel şeyler getirdi. Bunları bilmek ve projenize uygulamak, minimum çabayla maksimum kazanım sağlar.
XAML Kaynak Üreteci (Source Generator)
.NET 10 ile kullanıma giren XAML kaynak üreteci, .NET 11 Preview 1'de varsayılan olarak etkinleştirildi. Ne yapıyor? XAML dosyalarını derleme zamanında güçlü tipli C# koduna dönüştürüyor ve çalışma zamanı yükünü azaltıyor:
- Daha hızlı derleme süreleri
- Daha iyi IntelliSense desteği
- Çalışma zamanında XAML ayrıştırma ihtiyacının ortadan kalkması
- Daha iyi hata ayıklama deneyimi
<!-- .NET 11+ için varsayılan, .NET 10 için manuel etkinleştirme -->
<PropertyGroup>
<EnableXamlSourceGenerator>true</EnableXamlSourceGenerator>
</PropertyGroup>
Yeni CollectionView ve CarouselView Handler'ları
.NET 9'da opsiyonel olan gelişmiş handler'lar, .NET 10'da varsayılan oldu. Özellikle iOS ve Mac Catalyst'te CollectionView ve CarouselView için ciddi performans ve kararlılık iyileştirmeleri sunuyor.
SafeArea Yönetimi İyileştirmeleri
.NET 10'daki gelişmiş SafeAreaEdges kontrolü, iOS'ta ScrollView'deki o can sıkıcı ekstra alt boşluk sorununu çözüyor. Daha tutarlı bir platform davranışı elde ediyorsunuz.
.NET Aspire Entegrasyonu
.NET 10, .NET MAUI için bir Aspire servis varsayılanları proje şablonu sunuyor. Telemetri ve servis keşfi entegrasyonu artık çok daha kolay. Üretim ortamında performans izleme ve hata ayıklama için güçlü bir altyapı.
Profilleme Araçları ve Performans Analizi
Optimizasyona başlamadan önce mutlaka profilleme yapın. "Burası yavaş gibi geldi" diyerek sezgisel optimizasyon yapmak, çoğu zaman yanlış yere vakit harcamak demek. Veri odaklı yaklaşım her zaman kazanır.
dotnet-trace ile CPU Profilleme
dotnet-trace, .NET MAUI uygulamalarını Android, iOS, Mac ve Windows'ta profillemenize olanak tanır:
# Araçları kurun
dotnet tool install -g dotnet-trace
dotnet tool install -g dotnet-dsrouter
# Windows masaüstü uygulaması için doğrudan profilleme
dotnet-trace collect -- /yol/uygulama.exe
# Android için uzak profilleme
# 1. dsrouter başlatın
dotnet-dsrouter android
# 2. Yeni bir terminal'de ADB yönlendirmesi yapın
adb reverse tcp:9000 tcp:9001
adb shell setprop debug.mono.profile "127.0.0.1:9000,nosuspend,connect"
# 3. Uygulamayı başlatın ve trace toplayın
dotnet-trace collect -p <pid> --format speedscope
Oluşturulan .speedscope dosyasını speedscope.app üzerinde açarak flame graph ile darboğazları görsel olarak analiz edebilirsiniz. İlk kez kullandığınızda "neden daha önce kullanmamışım" diyeceksiniz.
Profilleme İçin Altın Kurallar
- Her zaman Release yapısında profil oluşturun. Debug yapıları yorumlayıcı kullanır, sonuçlar gerçekçi olmaz.
- Simülatörde profilleme yapmayın. Simülatör, cihaz performansını doğru yansıtmaz.
- En düşük hedef cihazda test edin. En yavaş desteklenen cihaz, gerçek kullanıcı deneyimini temsil eder.
- Diğer uygulamaları kapatın. Arka plan uygulamaları ölçüm sonuçlarını bozabilir.
- Önce profil oluşturun, sonra optimize edin. Sezgisel değil, veriye dayalı karar verin.
Performans Kontrol Listesi
Uygulamanızı yayınlamadan önce bu listeyi bir geçin:
- Derleme: Release modunda NativeAOT (iOS) veya Profiled AOT (Android) etkin mi?
- Trimming: Tam trimming etkin ve uyarılar giderildi mi?
- Başlangıç: Ağır servisler Lazy<T> ile ertelendi mi? Shell navigasyon kullanılıyor mu?
- CollectionView: ScrollView içine konulmadığından emin misiniz? MeasureFirstItem kullanılıyor mu?
- Bağlama: Compiled bindings (x:DataType) tüm sayfalarda etkin mi? Salt okunur veriler OneTime modunda mı?
- Layout: İç içe geçme derinliği 2-3 seviyeyi aşmıyor mu?
- Görseller: SVG/WebP kullanılıyor mu? Gereksiz büyük görseller optimize edildi mi?
- Bellek: Olay abonelikleri OnDisappearing'de kaldırılıyor mu? dotnet-gcdump ile sızıntı testi yapıldı mı?
- Profilleme: dotnet-trace ile başlangıç süresi ölçüldü mü? Hedef cihazlarda test edildi mi?
Sıkça Sorulan Sorular
.NET MAUI uygulamasının başlangıç süresini nasıl ölçerim?
dotnet-trace aracıyla başlangıç süresini hassas şekilde ölçebilirsiniz. Android'de adb logcat üzerinden ActivityManager loglarını filtreleyerek "Displayed" süresini görebilirsiniz. iOS tarafında ise Xcode Instruments'taki "App Launch" şablonu işinizi görür. En doğru sonuçlar için Release yapısında ve gerçek cihazda ölçüm yapın — simülatör sonuçlarına güvenmeyin.
CollectionView neden kaydırırken takılıyor?
En yaygın nedenler: ScrollView içine yerleştirme (sanallaştırmayı öldürür), karmaşık ItemTemplate, Reflection tabanlı bağlamalar ve optimize edilmemiş görseller. Çözüm olarak Grid içinde konumlandırın, ItemSizingStrategy="MeasureFirstItem" kullanın, compiled bindings etkinleştirin ve görselleri uygun boyutta yükleyin.
NativeAOT ve Profiled AOT arasındaki fark nedir?
Profiled AOT sadece başlatma yolundaki kritik metotları önceden derler, uygulama boyutunu minimal artırır. NativeAOT ise tüm kodu yerel makine koduna derleyerek Mono çalışma zamanını tamamen kaldırır — %50 daha küçük boyut ve 2 kat daha hızlı başlangıç. Ama NativeAOT şu an sadece iOS, MacCatalyst ve Windows'ta çalışıyor; Android için Profiled AOT kullanmanız gerekiyor.
.NET MAUI'de bellek sızıntısını nasıl tespit ederim?
dotnet-gcdump ile bellek anlık görüntüsü alın, Visual Studio veya PerfView ile analiz edin. Sızıntıların en yaygın kaynağı kaldırılmayan olay abonelikleri ve dispose edilmeyen kaynaklar. WeakEventManager ile olay yönetimini otomatikleştirebilir, MemoryToolkit.Maui ile sızıntıları otomatik tespit edebilirsiniz.
XAML kaynak üreteci performansı ne kadar etkiliyor?
XAML kaynak üreteci, XAML dosyalarını derleme zamanında güçlü tipli C# koduna dönüştürür. Çalışma zamanında XAML ayrıştırma ortadan kalkar, derleme süreleri kısalır, IntelliSense iyileşir. .NET 11 Preview 1'de varsayılan olan bu özellik, özellikle çok sayıda XAML sayfası olan projelerde gözle görülür bir başlangıç süresi iyileştirmesi sağlar.