Akademi C# · Pelajaran

ReadyToRun & Kompilasi Berperingkat

Fahami prakompilasi ReadyToRun, kompilasi JIT berperingkat dan PGO (pengoptimuman berpandukan profil) dalam .NET.

Pelajaran 3 daripada 412 langkah

ReadyToRun & Kompilasi Berperingkat ialah pelajaran Akademi C# percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Akademi C#, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Akademi C# merangkumi sejumlah 4 pelajaran.

JIT, R2R dan Kompilasi Berperingkat

.NET menggunakan beberapa strategi kompilasi untuk mengimbangi kelajuan permulaan dengan daya pemprosesan puncak. Memahami JIT, ReadyToRun dan Kompilasi Berperingkat membantu anda memilih tetapan yang sesuai untuk beban kerja anda.

Cara JIT Berfungsi

Pengkompil Just-in-Time (JIT) menukar baitkod IL kepada kod mesin natif pada kali pertama setiap kaedah dipanggil. Hal ini menambahkan kependaman pada panggilan pertama, tetapi menghasilkan kod yang sangat dioptimumkan 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 terhadap himpunan anda kepada kod natif pada masa penerbitan. Aplikasi bermula dengan lebih pantas kerana kerja JIT telah dilakukan, tetapi saiz pada cakera menjadi 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 berbanding Native AOT

R2R masih menghantar IL bersama kod natif dan masih memerlukan masa jalan .NET. Native AOT mengalih keluar IL dan masa jalan sepenuhnya. Buat pilihan berdasarkan keperluan penggunaan 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 startup

Kompilasi Berperingkat

Kompilasi Berperingkat didayakan secara lalai dalam .NET. Kaedah bermula pada Tier 0 (kompilasi pantas), dan kaedah yang kerap digunakan dikompil semula pada Tier 1 (pengoptimuman 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=0

Pengoptimuman Berpandukan Profil (PGO)

.NET 8+ menyertakan PGO Dinamik secara lalai. Masa jalan mengumpulkan data profil panggilan pada Tier 0, kemudian menggunakan profil tersebut untuk menjana kod Tier 1 yang sangat khusus bagi laluan yang kerap 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+)

Cangkuk Masa Mula

Cangkuk masa mula (DOTNET_STARTUP_HOOKS) membolehkan anda menyuntik kod sebelum Main dijalankan, berguna untuk diagnostik, penggantian konfigurasi atau instrumentasi tanpa mengubah suai kod 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]

Tetapan Konfigurasi Masa Jalan

Masa jalan .NET mendedahkan pemboleh ubah persekitaran dan tetapan runtimeconfig.json untuk melaraskan tingkah laku GC, kumpulan utas dan JIT tanpa perubahan kod.

// 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 throughput

Crossgen2 dan Imej Komposit

Crossgen2 ialah alat yang menghasilkan imej R2R. R2R komposit melakukan prakompilasi terhadap seluruh aplikasi (aplikasi + rangka kerja) menjadi satu imej natif yang dikongsi untuk permulaan yang 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 R2R

Contoh Dunia Sebenar: Melaraskan Permulaan ASP.NET Core

Senarai semak tetapan praktikal untuk memaksimumkan prestasi permulaan dalam perkhidmatan ASP.NET Core pengeluaran.

// .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");

Semakan Pantas

Apakah perbezaan utama antara ReadyToRun (R2R) dengan Native AOT?

Ringkasan: ReadyToRun & Kompilasi Berperingkat

Kesimpulan utama:

  • Kompilasi Berperingkat: lalai dalam .NET — Tier 0 (kompilasi pantas) → Tier 1 (dioptimumkan + PGO)
  • PGO Dinamik: lalai .NET 8+ — masa jalan membuat profil laluan yang kerap digunakan dan mengkhususkan kod Tier 1
  • ReadyToRun: melakukan prakompilasi semasa penerbitan; permulaan ~30% lebih pantas; masih memerlukan masa jalan; menyokong refleksi
  • Native AOT: tiada IL, tiada masa jalan; permulaan ~36x lebih pantas; tiada refleksi; perduaan paling kecil
  • Laraskan melalui runtimeconfig.json dan pemboleh ubah persekitaran (tetapan GC, kumpulan utas dan JIT)
  • R2R komposit menggabungkan aplikasi + rangka kerja menjadi satu imej natif untuk permulaan terbaik
Percuma untuk bermula

Pelajari C# dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
93
Pelajaran
346

Soalan Lazim

Adakah pelajaran “ReadyToRun & Kompilasi Berperingkat” percuma?

Ya — teks penuh “ReadyToRun & Kompilasi Berperingkat” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Akademi C#, tingkat taraf kepada CoddyKit PRO. Kursus Akademi C# merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “ReadyToRun & Kompilasi Berperingkat”?

Fahami prakompilasi ReadyToRun, kompilasi JIT berperingkat dan PGO (pengoptimuman berpandukan profil) dalam .NET. Anda berlatih Akademi C# menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Akademi C#?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Akademi C# di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.

Berapa lamakah pelajaran “ReadyToRun & Kompilasi Berperingkat” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Akademi C# ini?

Ya. Setiap pelajaran Akademi C# menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Kompilasi AOT Asli
  2. Had Pemangkasan & Pantulan
  3. ReadyToRun & Kompilasi Berperingkat
  4. Penanda Aras dengan BenchmarkDotNet
← Kembali ke Akademi C#