Episode ini mengajarkan cara mengukur dan memperbaiki performa: profiling dengan dotnet-trace dan dotnet-counters, memory diagnostics dan GC tuning, Span dan Memory untuk alokasi minimal, serta hot reload, tiered compilation, dan pertimbangan AOT.

Aplikasi yang benar belum tentu cepat. Episode 15 membahas performance dan diagnostics: bagaimana mengukur perilaku aplikasi dengan data, menemukan bottleneck, dan menerapkan teknik optimasi yang tepat. Aturan utamanya: ukur dulu, optimasi kemudian.
Kalian akan berkenalan dengan alat profiling resmi .NET, menganalisis alokasi memori, mengenal Span<T> untuk kode alokasi minimal, serta memahami hot reload, tiered compilation, dan kapan AOT layak dipakai. Optimasi tanpa pengukuran hanyalah tebakan.
Alat diagnostik .NET diinstall sebagai global tool:
dotnet tool install --global dotnet-trace
dotnet tool install --global dotnet-counters
dotnet tool install --global dotnet-dumpdotnet-trace, dotnet-counters, dan dotnet-dump adalah trio diagnostik utama. dotnet-counters memantau metrik secara real-time; dotnet-trace mengumpulkan trace yang bisa dianalisis lebih dalam.
Jalankan aplikasi dan amati metrik CPU, GC, dan memori:
dotnet-counters monitor --process-id 12345dotnet-counters monitor --process-id 12345 menampilkan metrik seperti cpu-usage, working-set, dan jumlah alokasi per detik. Layar ini langsung memperlihatkan apakah aplikasi sibuk dengan GC atau sedang mengalokasi memori secara tidak wajar.
Untuk investigasi mendalam, kumpulkan trace:
dotnet-trace collect --process-id 12345 --profile gc-verbosedotnet-trace collect --profile gc-verbose merekam aktivitas GC dan alokasi ke file trace. File ini bisa dibuka dengan dotnet-trace report atau alat seperti PerfView untuk menemukan objek yang paling banyak dialokasikan.
GC bekerja otomatis, tetapi tetap bisa dioptimasi. Metrik kunci:
Tuning utama adalah mengurangi alokasi yang tidak perlu. Antara lain dengan memakai koleksi dengan kapasitas awal, menghindari closure yang menangkap state besar, dan memakai ArrayPool untuk buffer sementara. Hindari men-set GC secara agresif tanpa data — di mayoritas kasus, pengurangan alokasi lebih efektif daripada mengubah mode GC.
Span<T> merepresentasikan wilayah memori yang bisa diakses tanpa alokasi heap:
Span<int> angka = stackalloc int[] { 1, 2, 3, 4, 5 };
foreach (ref var n in angka)
{
n *= 2;
}stackalloc mengalokasikan array di stack — tidak ada tekanan GC sama sekali. Span<T> bekerja pada memori berdekatan (contiguous) dan menjadi dasar optimasi seperti parsing dan serialisasi berperforma tinggi.
Memory<T> adalah versi Span<T> yang aman untuk data yang hidup melewati method (misalnya disimpan di Task). Aturan praktis: gunakan Span<T> untuk operasi lokal singkat, Memory<T> saat data perlu disimpan atau dikirim ke metode lain. Keduanya menghindari salinan data yang tidak perlu.
Hot reload memungkinkan perubahan kode diterapkan tanpa restart. Jalankan dengan:
dotnet watch rundotnet watch run memantau file sumber dan menerapkan perubahan secara live. Di produksi, fitur ini tidak dipakai — tetapi saat pengembangan, ia memangkas waktu iterasi secara drastis.
Tiered compilation diaktifkan default: metode dijalankan cepat dengan JIT ringan (tier 0), lalu dioptimasi lebih agresif saat terbukti panas (tier 1). Hasilnya startup cepat dan performa steady-state tinggi. Untuk beban yang membutuhkan startup secepat mungkin, pertimbangkan menonaktifkan tiering atau memakai AOT.
NativeAOT mengkompilasi seluruh aplikasi ke native saat publish:
dotnet publish -c Release -r linux-x64 -p:PublishAot=truedotnet publish -c Release -r linux-x64 -p:PublishAot=true menghasilkan binary native tanpa runtime terpisah. Keuntungannya startup instan dan footprint kecil — ideal untuk serverless dan edge. Keterbatasannya: reflection dibatasi dan performa JIT yang adaptif tidak tersedia, jadi AOT bukan untuk semua workload.
Tip
Optimasi dimulai dari pengukuran. Profil aplikasi dengan dotnet-counters dan dotnet-trace sebelum mengubah kode — perubahan tanpa data berisiko memperburuk keadaan.
Inti yang harus dibawa pulang:
Span<T> mengakses memori tanpa alokasi; stackalloc untuk stack.Di episode 16 selanjutnya kita akan membahas advanced architecture dan patterns — clean architecture, layered architecture, dan modular monolith, mediator dan event-driven design, CQRS dan domain-driven design, serta service composition dan bounded contexts.