در این بخش، به بررسی نحوه بهینهسازی یک اپلیکیشن با استفاده از Visual Studio Profiler میپردازیم. این ابزار به شما کمک میکند تا گلوگاههای عملکردی (Performance Bottlenecks) را شناسایی و برنامهتان را بهینهسازی کنید.
بهینهسازی برنامه با استفاده از Profiler در Visual Studio
استفاده از Visual Studio Profiler شامل چند مرحله کلیدی برای شناسایی مشکلات عملکردی مانند مصرف حافظه، پیچیدگی زمانی، میزان استفاده از CPU و … است.
در این مقاله، یاد میگیرید که:
چطور تحلیل کد (Code Analysis) را در Visual Studio اجرا کنید.
و چطور از Profiler برای بهینهسازی کد برنامهنویسی استفاده کنید.
ایجاد برنامه نمونه در #C
ابتدا یک اپلیکیشن کنسولی ساده بسازید و متد زیر را ایجاد کنید:
public static void TestWriteFileToDisk(int numberOfRecord)
{
for (int i = 1; i <= numberOfRecord; i++)
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings[“cn”].ConnectionString))
{
if (cn.State == System.Data.ConnectionState.Closed)
cn.Open();
using (SqlCommand cmd = new SqlCommand($”select ProductName from Products where ProductID={i}”, cn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
System.IO.File.AppendAllText($”{Application.StartupPath}\\data.txt”, $”{i}: {reader.GetString(0)}\n”);
}
}
}
}
}
پیکربندی فایل App.config
<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
<startup>
<supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.5.2″ />
</startup>
<connectionStrings>
<add name=”cn” connectionString=”Data Source=.;Initial Catalog=Northwind;User ID=sa;Password=123@qaz;” providerName=”System.Data.SqlClient”/>
</connectionStrings>
</configuration>
اینجا از پایگاه دادهی Northwind برای اجرای دمو استفاده شده است. متد TestWriteFileToDisk دادههایی از جدول محصولات (Products) میخواند و در یک فایل متنی ذخیره میکند.
بررسی قبل و بعد از بهینهسازی
بعد از اجرای اولیه و ثبت اطلاعات توسط Profiler، میتوانید کد را بازنویسی و بهینه کنید، سپس دوباره پروفایل بگیرید تا تفاوت عملکرد را مشاهده کنید.
اجرای برنامه در Visual Studio
در متد Main کد زیر را قرار دهید:
static void Main(string[] args)
{
// برای اجرای بدون دیباگ Ctrl+F5 را بزنید
TestWriteFileToDisk(77);
Console.WriteLine(“Finished !”);
Console.ReadKey();
}
اجرای Code Analysis و Profiler در Visual Studio 2017 یا ۲۰۱۹
حالت پروژه را از “Debug” به “Release” تغییر دهید.
از منو مسیر زیر را انتخاب کنید:
Analyze => Performance Profiler
حالا میتوانید نوع آنالیز (مثلاً CPU Usage، Memory Usage و …) را انتخاب کرده و برنامه را اجرا کنید تا اطلاعات عملکردی دریافت کنید.

روی Performance Wizard کلیک کرده و سپس دکمه Start را فشار دهید.

انتخاب گزینه Instrumentation (ابزارسنجی).

انتخاب یک یا چند پروژهی موجود.

انتخاب پروژهی خود، سپس کلیک روی دکمهی Next (بعدی).

در نهایت، روی دکمهی Finish (پایان) کلیک کنید.
وقتی در برنامه عبارت “Finished !” را دیدید، برنامه را ببندید.

میتوانید ببینید که درصد استفاده از CPU در نمودار بالا همیشه بالا است.

متد AppendAllText، ۴۲.۷۳ درصد از منابع را مصرف میکند.
حال کد خود را به صورت زیر بهینهسازی خواهیم کرد:
public static void TestWriteFileToDisk(int numberOfRecord)
{
string connectionString = ConfigurationManager.ConnectionStrings[“cn”].ConnectionString;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 1; i <= numberOfRecord; i++)
{
using (SqlConnection cn = new SqlConnection(connectionString))
{
if (cn.State == System.Data.ConnectionState.Closed)
cn.Open();
using (SqlCommand cmd = new SqlCommand($”select ProductName from Products where ProductID={i}”, cn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
stringBuilder.Append($”{i}: {reader.GetString(0)}\n”);
}
}
}
}
System.IO.File.AppendAllText($”{Application.StartupPath}\\data.txt”, stringBuilder.ToString());
}
اتصال به پایگاه داده را از داخل حلقه خارج کردیم و از StringBuilder برای اتصال متن به جای نوشتن مستقیم به فایل استفاده کردیم. در نهایت، متغیر stringBuilder را به رشته تبدیل کرده و آن را به فایل مینویسیم.
ما همچنان از Visual Studio Profiler برای بهینهسازی کد خود استفاده خواهیم کرد.

همانطور که در نمودار بالا میبینید، زمان اجرای برنامه را از ۱.۳۵۲ ثانیه به ۰.۲۰۵ ثانیه کاهش دادهایم.

همانطور که مشاهده میکنید، استفاده از متد AppendAllText به ۴.۸۴% کاهش یافته است.
public static void TestWriteFileToDisk(int numberOfRecord)
{
string connectionString = ConfigurationManager.ConnectionStrings[“cn”].ConnectionString;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 1; i <= numberOfRecord; i++)
{
using (SqlConnection cn = new SqlConnection(connectionString))
{
if (cn.State == System.Data.ConnectionState.Closed)
cn.Open();
using (SqlCommand cmd = new SqlCommand($”select ProductName from Products where ProductID={i}”, cn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
stringBuilder.AppendFormat(“{0}: {1}\n”, i, reader.GetString(0));
}
}
}
}
System.IO.File.AppendAllText($”{Application.StartupPath}\\data.txt”, stringBuilder.ToString());
}
در اینجا به جای استفاده از متد Append از AppendFormat در StringBuilder استفاده کردهایم.

پس از اجرای برنامه خود، Visual Studio Profiler دادهها را در مورد معیارهای عملکرد یا استفاده از حافظه جمعآوری خواهد کرد.
دادههای خود را تجزیه و تحلیل کنید تا هر گونه ناحیهای که نیاز به توجه یا بهینهسازی دارد شناسایی کنید. Visual Studio ابزارها و نماهای مختلفی برای کمک به این تحلیل ارائه میدهد، مانند Call Tree، CPU Usage، Memory Usage و موارد دیگر.
سپس به دنبال توابع یا بلوکهای کدی بگردید که زمان زیادی از CPU یا حافظه را مصرف میکنند. پس از شناسایی نواحی نیازمند بهینهسازی، تغییرات لازم را در کد خود اعمال کنید.
تمرکز خود را روی بخشهای بحرانی عملکردی کد قرار دهید، مانند حلقهها یا توابعی که به طور مکرر فراخوانی میشوند.
بهینهسازیهایی مانند بهبود الگوریتمها، کاهش تخصیصهای غیرضروری حافظه یا حداقل کردن عملیات ورودی/خروجی را در نظر بگیرید.
پس از انجام بهینهسازیها، برنامه خود را دوباره با پروفایلر اجرا کنید تا تأثیر تغییرات خود را اندازهگیری کنید.
فرآیند بهینهسازی را تکرار کنید و در صورت لزوم تغییرات بیشتری اعمال کنید.
برنامه خود را به طور کامل آزمایش کنید تا مطمئن شوید که بهینهسازیها باعث ایجاد مشکلات جدید یا بازگشت به مشکلات قبلی نشدهاند.












