ReadyToRun & Kompilasi Bertingkat
Pahami prakompilasi ReadyToRun, kompilasi JIT bertingkat, dan PGO (optimisasi berbasis profil) di .NET.
ReadyToRun & Kompilasi Bertingkat adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 4 pelajaran total.
JIT, R2R, dan Kompilasi Bertingkat
.NET menggunakan beberapa strategi kompilasi untuk menyeimbangkan kecepatan waktu mulai dengan laju pemrosesan maksimum. Memahami JIT, ReadyToRun, dan Kompilasi Bertingkat membantu Anda memilih pengaturan yang tepat untuk beban kerja Anda.
Cara Kerja JIT
Kompiler Just-in-Time (JIT) mengonversi bytecode IL menjadi kode mesin natif saat pertama kali setiap metode dipanggil. Hal ini menambah latensi pada pemanggilan pertama, tetapi menghasilkan kode yang sangat dioptimalkan untuk mesin yang sedang menjalankan aplikasi.
// What happens at runtime:
// 1. App starts — methods are stubs pointing to the JIT
// 2. First call to MyMethod() → JIT compiles IL → native x64 code
// 3. Subsequent calls → native code runs directly (no JIT overhead)
// Startup cost: each method's first call takes microseconds for JIT
// Peak performance: excellent — JIT knows the actual CPU features
// .NET 9 JIT optimizations applied automatically:
// - Inlining
// - Loop unrolling
// - Escape analysis
// - SIMD vectorization
// - Profile-Guided Optimization (PGO)Kompilasi ReadyToRun (R2R)
ReadyToRun (R2R) melakukan prakompilasi rakitan menjadi kode natif saat publikasi. Aplikasi mulai lebih cepat karena pekerjaan JIT sudah selesai, dengan konsekuensi ukuran di disk yang lebih besar.
// Enable R2R in .csproj:
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
<!-- Optional: composite R2R — whole app in one native image -->
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
</PropertyGroup>
// Publish:
dotnet publish -c Release -r linux-x64 --self-contained
// Benefits:
// - Startup time improvement: ~20-30% faster than JIT-only
// - No runtime required (self-contained)
// Trade-off:
// - Larger binary (IL + R2R code both stored)
// - Publish takes longer (cross-gen2 runs at publish time)R2R vs Native AOT
R2R masih menyertakan IL di samping kode natif dan tetap memerlukan lingkungan eksekusi .NET. Native AOT menghapus IL dan lingkungan eksekusi sepenuhnya. Pilih berdasarkan persyaratan penerapan Anda.
// ReadyToRun:
// ✓ Still ships IL (fallback JIT for dynamically-generated code)
// ✓ Supports full reflection
// ✓ .NET runtime required on target
// ✓ Startup: ~30% faster than JIT
// Size: medium (IL + native)
// Native AOT:
// ✓ No IL, no runtime needed on target
// ✓ Startup: ~36x faster than JIT
// ✗ No reflection (must use source generators)
// ✗ Trimming limitations
// Size: smallest
// JIT only:
// ✓ Full reflection, no limitations
// ✓ Best peak throughput via PGO
// ✗ Slowest startupKompilasi Bertingkat
Kompilasi Bertingkat diaktifkan secara default di .NET. Metode dimulai pada Tingkat 0 (kompilasi cepat), lalu metode yang sering digunakan dikompilasi ulang pada Tingkat 1 (optimisasi penuh) di latar belakang.
// Tiered compilation lifecycle:
// Tier 0: fast JIT with minimal optimization
// → method is callable in ~100 microseconds
// After ~30 calls (configurable): marked as "hot"
// Tier 1: full JIT with all optimizations + PGO
// → background thread re-compiles the method
// → future calls use optimized native code
// Usually transparent — you don't need to configure it
// Disable (rarely needed, only for debugging JIT issues):
// DOTNET_TieredCompilation=0
// Disable tiered PGO if benchmarking:
// DOTNET_TieredPGO=0Optimisasi Berpanduan Profil (PGO)
.NET 8+ menyertakan Dynamic PGO secara default. Lingkungan eksekusi mengumpulkan data profil pemanggilan pada Tingkat 0, lalu menggunakan profil tersebut untuk menghasilkan kode Tingkat 1 yang sangat terspesialisasi untuk jalur yang sering digunakan.
// PGO automatically specializes code like:
// Before PGO (generic virtual dispatch):
void Process(IAnimal animal) => animal.Speak();
// → runtime checks type on every call
// After PGO (type-specialized inline):
void Process(IAnimal animal)
{
if (animal is Dog) { /* inlined Dog.Speak() */ }
else if (animal is Cat){ /* inlined Cat.Speak() */ }
else animal.Speak(); // slow path
}
// Enabled by default in .NET 8+
// Verify:
// DOTNET_ReadyToRun=0
// DOTNET_TieredCompilation=1 (default)
// DOTNET_TieredPGO=1 (default .NET 8+)Pengait Waktu Mulai
Pengait waktu mulai (DOTNET_STARTUP_HOOKS) memungkinkan Anda menyisipkan kode sebelum Main berjalan, berguna untuk diagnosis, penggantian konfigurasi, atau instrumentasi tanpa mengubah kode aplikasi.
// Create a hook class:
public class StartupHook
{
public static void Initialize()
{
Console.WriteLine("[StartupHook] Initializing before Main");
// e.g., register telemetry, inject config overrides
Environment.SetEnvironmentVariable("FEATURE_FLAG", "1");
}
}
// Compile to a DLL and set the env var:
export DOTNET_STARTUP_HOOKS=/path/to/MyHook.dll
// Then run your app normally:
dotnet run
// [StartupHook] Initializing before Main
// [Your App Output]Parameter Konfigurasi Lingkungan Eksekusi
Lingkungan eksekusi .NET menyediakan variabel lingkungan dan parameter runtimeconfig.json untuk menyetel GC, kumpulan utas, dan perilaku JIT tanpa perubahan kode.
// runtimeconfig.template.json (baked into app at publish):
{
"configProperties": {
"System.GC.Server": true, // server GC (multi-core)
"System.GC.Concurrent": true, // background GC
"System.GC.HeapHardLimit": 536870912, // 512 MB hard limit
"System.Threading.ThreadPool.MinThreads": 20,
"System.Threading.ThreadPool.MaxThreads": 200,
"System.Runtime.TieredCompilation": true
}
}
// Environment variable overrides (useful in containers):
// DOTNET_GCHeapHardLimit=536870912
// DOTNET_ThreadPool_UnfairSemaphoreSpinLimit=70
// DOTNET_GCConserve=1 // reduce memory at cost of throughputCrossgen2 dan Citra Komposit
Crossgen2 adalah alat yang menghasilkan citra R2R. R2R komposit melakukan prakompilasi seluruh aplikasi (aplikasi + kerangka kerja) menjadi satu citra natif bersama untuk waktu mulai sebaik mungkin.
// Composite R2R: compile app + framework into one native image
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
</PropertyGroup>
// Normal R2R includes multiple images per assembly
// Composite merges them → fewer file reads at startup
// Manual crossgen2 invocation:
dotnet tool install -g dotnet-crossgen2
crossgen2 \
--composite \
--out composite.dll \
MyApp.dll framework/System.Runtime.dll
// Inspect R2R content:
dotnet-ildasm --methodheader MyApp.dll | grep --color R2RDunia Nyata: Menyetel Waktu Mulai ASP.NET Core
Daftar periksa pengaturan praktis untuk memaksimalkan kinerja waktu mulai dalam layanan ASP.NET Core produksi.
// .csproj:
<PublishReadyToRun>true</PublishReadyToRun> // pre-JIT at publish
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
<TieredCompilation>true</TieredCompilation> // default
// Program.cs — avoid startup work:
// ✓ Use AddHealthChecks() NOT AddDbContextCheck() for faster probe
// ✓ Lazy-initialize expensive singletons
// ✓ Don't await long tasks in Program.cs before app.Run()
// Container settings:
// DOTNET_GCServer=1 → server GC for multi-core pods
// DOTNET_GCHeapHardLimit=536870912 → prevent OOM in constrained pods
// DOTNET_ThreadPool_MinThreads=20 → reduce thread starvation under burst load
// Measure startup:
// app.MapGet("/startup-time",
// () => $"Ready in: {Stopwatch.GetElapsedTime(startTimestamp).TotalMs}ms");Pemeriksaan Singkat
Apa perbedaan utama antara ReadyToRun (R2R) dan Native AOT?
Ringkasan: ReadyToRun dan Kompilasi Bertingkat
Hal penting:
- Kompilasi Bertingkat: default di .NET — Tingkat 0 (kompilasi cepat) → Tingkat 1 (dioptimalkan + PGO)
- Dynamic PGO: default di .NET 8+ — lingkungan eksekusi membuat profil jalur yang sering digunakan dan mengkhususkan kode Tingkat 1
- ReadyToRun: melakukan prakompilasi saat publikasi; waktu mulai sekitar 30% lebih cepat; tetap memerlukan lingkungan eksekusi; mendukung refleksi
- Native AOT: tanpa IL, tanpa lingkungan eksekusi; waktu mulai sekitar 36 kali lebih cepat; tanpa refleksi; biner terkecil
- Setel melalui
runtimeconfig.jsondan variabel lingkungan (parameter GC, kumpulan utas, dan JIT) - R2R komposit menggabungkan aplikasi + kerangka kerja menjadi satu citra natif untuk waktu mulai terbaik
Pertanyaan yang Sering Diajukan
Apakah pelajaran “ReadyToRun & Kompilasi Bertingkat” gratis?
Ya — teks lengkap “ReadyToRun & Kompilasi Bertingkat” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “ReadyToRun & Kompilasi Bertingkat”?
Pahami prakompilasi ReadyToRun, kompilasi JIT bertingkat, dan PGO (optimisasi berbasis profil) di .NET. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai C# Academy?
Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “ReadyToRun & Kompilasi Bertingkat” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?
Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Kompilasi Native AOT
- Keterbatasan Trimming & Reflection
- ReadyToRun & Kompilasi Bertingkat
- Benchmark dengan BenchmarkDotNet