Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Mengoptimalkan kode Anda mengurangi waktu dan biaya komputasi. Studi kasus ini menunjukkan cara menggunakan alat pembuatan profil Visual Studio untuk mengidentifikasi dan memperbaiki masalah performa dalam sampel aplikasi .NET. Jika Anda ingin membandingkan alat pembuatan profil, lihat Alat mana yang harus saya pilih?
Panduan ini mencakup:
- Cara menggunakan alat pembuatan profil Visual Studio untuk menganalisis dan meningkatkan performa.
- Strategi praktis untuk mengoptimalkan penggunaan CPU, alokasi memori, dan interaksi database.
Terapkan teknik ini untuk membuat aplikasi Anda sendiri lebih efisien.
Studi kasus pengoptimalan
Contoh aplikasi .NET menjalankan kueri terhadap database SQLite blog dan posting menggunakan Entity Framework. Ini menjalankan banyak kueri, mensimulasikan skenario pengambilan data dunia nyata. Aplikasi ini didasarkan pada contoh pengantar Kerangka Kerja Entitas, tetapi menggunakan himpunan data yang lebih besar.
Masalah performa utama meliputi:
- Penggunaan CPU Tinggi: Komputasi atau tugas pemrosesan yang tidak efisien meningkatkan konsumsi dan biaya CPU.
- Alokasi Memori Tidak Efisien: Manajemen memori yang buruk menyebabkan pengumpulan sampah yang berlebihan dan pengurangan performa.
- Peningkatan Beban Database: Kueri yang tidak efisien dan panggilan database yang berlebihan mengurangi kinerja.
Studi kasus ini menggunakan alat pembuatan profil Visual Studio untuk menentukan dan mengatasi masalah ini, yang bertujuan untuk membuat aplikasi lebih efisien dan hemat biaya.
Tantangan
Memperbaiki masalah performa ini melibatkan beberapa tantangan:
- Mendiagnosis Hambatan: Mengidentifikasi akar penyebab overhead CPU, memori, atau database yang tinggi memerlukan penggunaan alat pembuatan profil yang efektif dan interpretasi hasil yang benar.
- Batasan Pengetahuan dan Sumber Daya: Pembuatan profil dan pengoptimalan memerlukan keterampilan dan pengalaman tertentu, yang mungkin tidak selalu tersedia.
Pendekatan strategis yang menggabungkan alat pembuatan profil, pengetahuan teknis, dan pengujian yang cermat sangat penting untuk mengatasi tantangan ini.
Strategi
Berikut adalah tampilan tingkat tinggi dari pendekatan dalam studi kasus ini:
- Mulailah dengan pelacakan penggunaan CPU menggunakan alat Penggunaan CPU Visual Studio. Alat Penggunaan CPU Visual Studio adalah titik awal yang baik untuk penyelidikan performa.
- Kumpulkan jejak tambahan untuk analisis memori dan database:
- Gunakan alat Alokasi Objek .NET untuk wawasan memori.
- Gunakan alat Database untuk memeriksa kueri dan waktu SQL.
Pengumpulan data memerlukan tugas berikut:
- Atur aplikasi ke versi rilis.
- Pilih alat Penggunaan CPU di Profiler Performa (Alt+F2).
- Di Profiler Performa, mulai aplikasi dan kumpulkan jejak.
Memeriksa area penggunaan CPU yang tinggi
Setelah mengumpulkan jejak dengan alat Penggunaan CPU dan memuatnya ke Visual Studio, pertama-tama kita periksa halaman laporan .diagsession awal yang menampilkan data ringkasan. Gunakan tautan Buka detail dalam laporan.
Dalam tampilan detail laporan, buka tampilan Pohon Panggilan. Jalur kode dengan penggunaan CPU tertinggi dalam aplikasi disebut jalur panas . Ikon nyala jalur panas (
) dapat membantu mengidentifikasi masalah performa yang mungkin ditingkatkan dengan cepat.
Dalam tampilan Pohon Panggilan, Anda dapat melihat penggunaan CPU yang tinggi oleh metode GetBlogTitleX di aplikasi, yang menggunakan sekitar 60% persen dari penggunaan CPU aplikasi tersebut. Namun, nilai CPU Mandiri untuk GetBlogTitleX rendah, hanya sekitar .10%. Tidak seperti Total CPU, nilai CPU Diri Sendiri mengecualikan waktu yang dihabiskan dalam fungsi lain, sehingga kita tahu harus melihat lebih jauh ke bagian bawah pohon panggilan untuk menemukan hambatan yang sebenarnya.
GetBlogTitleX melakukan panggilan eksternal ke dua DLL LINQ, yang menggunakan sebagian besar waktu CPU, sebagaimana dibuktikan oleh nilai CPU Mandiri yang sangat tinggi. Ini adalah petunjuk pertama bahwa kueri LINQ mungkin merupakan area untuk dioptimalkan.
Untuk mendapatkan pohon panggilan yang divisualisasikan dan tampilan data yang berbeda, buka tampilan Flame Graph. (Atau, klik kanan GetBlogTitleX dan pilih Tampilan di Grafik Api.) Di sini lagi, sepertinya metode GetBlogTitleX bertanggung jawab atas banyak penggunaan CPU aplikasi (ditampilkan dalam warna kuning). Panggilan eksternal ke DLL LINQ muncul di bawah kotak GetBlogTitleX, dan mereka menggunakan semua waktu CPU untuk metode tersebut.
Mengumpulkan data tambahan
Seringkali, alat lain dapat memberikan informasi tambahan untuk membantu analisis dan mengisolasi masalah. Dalam studi kasus ini, kami mengambil pendekatan berikut:
- Pertama, lihat penggunaan memori. Mungkin ada korelasi antara penggunaan CPU yang tinggi dan penggunaan memori yang tinggi, sehingga dapat membantu untuk melihat keduanya untuk mengisolasi masalah.
- Karena kami mengidentifikasi DLL LINQ, kami juga akan melihat alat Database.
Periksa penggunaan memori
Untuk melihat apa yang terjadi dengan aplikasi dalam hal penggunaan memori, kami mengumpulkan jejak menggunakan alat Alokasi Objek .NET (Untuk C++, Anda dapat menggunakan alat Penggunaan Memori sebagai gantinya). Tampilan Pohon Panggilan dalam jejak memori menunjukkan jalur kritis yang membantu kami mengidentifikasi area dengan penggunaan memori tinggi. Tidak mengherankan pada titik ini, metode GetBlogTitleX tampaknya menghasilkan banyak objek! Lebih dari 900.000 alokasi objek, pada kenyataannya.
Sebagian besar objek yang dibuat adalah string, array objek, dan Int32s. Kita mungkin dapat melihat bagaimana jenis ini dihasilkan dengan memeriksa kode sumber.
Periksa kueri di alat Database
Di Profiler Performa, kami memilih alat Database alih-alih Penggunaan CPU (atau, pilih keduanya). Setelah mengumpulkan jejak, buka tab Kueri di halaman diagnostik. Di tab Kueri untuk pelacakan Database, Anda dapat melihat baris pertama memperlihatkan kueri terpanjang, 2446 milidetik. Kolom Rekaman memperlihatkan berapa banyak rekaman yang dibaca kueri. Anda dapat menggunakan informasi ini untuk perbandingan nanti.
Dengan memeriksa pernyataan SELECT yang dihasilkan oleh LINQ di kolom Kueri, kami mengidentifikasi baris pertama sebagai kueri yang terkait dengan metode GetBlogTitleX. Untuk menampilkan string kueri lengkap, perluas lebar kolom. String kueri lengkapnya adalah:
SELECT "b"."Url", "b"."BlogId", "p"."PostId", "p"."Author", "p"."BlogId", "p"."Content", "p"."Date", "p"."MetaData", "p"."Title"
FROM "Blogs" AS "b" LEFT JOIN "Posts" AS "p" ON "b"."BlogId" = "p"."BlogId" ORDER BY "b"."BlogId"
Perhatikan bahwa aplikasi mengambil banyak nilai kolom di sini, mungkin lebih dari yang kita butuhkan. Mari kita lihat kode sumbernya.
Mengoptimalkan kode
Saatnya untuk melihat kode sumber GetBlogTitleX. Di alat Database, klik kanan kueri dan pilih Buka File Sumber. Dalam kode sumber untuk GetBlogTitleX, kami menemukan kode berikut yang menggunakan LINQ untuk membaca database.
foreach (var blog in db.Blogs.Select(b => new { b.Url, b.Posts }).ToList())
{
foreach (var post in blog.Posts)
{
if (post.Author == "Fred Smith")
{
Console.WriteLine($"Post: {post.Title}");
}
}
}
Kode ini menggunakan perulangan foreach untuk mencari database untuk blog apa pun dengan "Fred Smith" sebagai penulis. Melihatnya, Anda dapat melihat bahwa banyak objek dihasilkan dalam memori: array objek baru untuk setiap blog dalam database, string terkait untuk setiap URL, dan nilai untuk properti yang terkandung dalam postingan, seperti ID blog.
Kami melakukan sedikit penelitian dan menemukan beberapa rekomendasi umum tentang cara mengoptimalkan kueri LINQ. Atau, kita dapat menghemat waktu dan membiarkan Copilot melakukan penelitian untuk kita.
Jika kita menggunakan Copilot, kita memilih Ask Copilot dari menu konteks dan ketik pertanyaan berikut:
Can you make the LINQ query in this method faster?
Tips
Anda dapat menggunakan perintah garis miring seperti /optimize untuk membantu membentuk pertanyaan yang baik untuk Copilot.
Dalam contoh ini, Copilot memberikan perubahan kode yang disarankan berikut, bersama dengan penjelasan.
public void GetBlogTitleX()
{
var posts = db.Posts
.Where(post => post.Author == "Fred Smith")
.Select(post => post.Title)
.ToList();
foreach (var postTitle in posts)
{
Console.WriteLine($"Post: {postTitle}");
}
}
Kode ini mencakup beberapa perubahan untuk membantu mengoptimalkan kueri:
- Menambahkan klausa
Wheredan menghilangkan salah satu perulanganforeach. - Memproyeksikan properti Judul saja dalam pernyataan
Select, yang kita butuhkan di contoh ini.
Selanjutnya, kami mencoba kembali menggunakan alat pembuatan profil.
Hasil
Setelah memperbarui kode, kami menjalankan kembali alat Penggunaan CPU untuk mengumpulkan jejak. Tampilan Pohon Panggilan menunjukkan bahwa GetBlogTitleX hanya berjalan 1754 ms, menggunakan 37% dari total CPU aplikasi, peningkatan signifikan dari 59%.
Beralih ke tampilan Flame Graph untuk melihat visualisasi lain yang menunjukkan peningkatan. Dalam tampilan ini, GetBlogTitleX juga menggunakan bagian CPU yang lebih kecil.
Periksa hasilnya di pelacakan alat Database, dan hanya dua rekaman yang dibaca menggunakan kueri ini, bukan 100.000! Selain itu, kueri jauh lebih disederhanakan dan menghilangkan LEFT JOIN yang tidak diperlukan sebelumnya.
Selanjutnya, kami memeriksa kembali hasil di alat Alokasi Objek .NET, dan melihat bahwa GetBlogTitleX hanya bertanggung jawab atas 56.000 alokasi objek, hampir pengurangan sebesar 95% dari 900.000!
Mengulangi
Beberapa pengoptimalan mungkin diperlukan dan kami dapat terus melakukan iterasi dengan perubahan kode untuk melihat perubahan mana yang meningkatkan performa dan membantu mengurangi biaya komputasi.
Langkah berikutnya
Artikel dan posting blog berikut ini menyediakan informasi selengkapnya untuk membantu Anda belajar menggunakan alat performa Visual Studio secara efektif.
- Studi kasus: Mengisolasi masalah performa
- Studi Kasus: Performa ganda dalam waktu kurang dari 30 menit
- Meningkatkan kinerja Visual Studio dengan Alat Instrumentasi baru