ج# بهینه سازی عملکرد: از مبتدی تا متخصص

در دنیای توسعه نرم افزار ، سرعت همه چیز است. این که آیا شما در حال ایجاد یک برنامه مالی مهم برای ماموریت هستید یا یک بازی موبایل ، کاربران انتظار دارند که برنامه شما به طور کارآمد عمل کند. C#، با مجموعه ویژگی های قوی و انتزاع سطح بالا ، یک زبان خارق العاده برای ایجاد برنامه های قدرتمند است ، اما حتی بهترین کد می تواند از تنظیم عملکرد بهره مند شود.
در این پست وبلاگ ، ما عمیقاً به بهینه سازی عملکرد در C#شیرجه می زنیم. شما یاد می گیرید که چگونه تنگناها را شناسایی کنید ، از تکنیک های بهینه سازی استفاده کنید و کد بسیار کارآمد بنویسید. این که آیا شما تازه شروع به کار خود کرده اید یا به دنبال تیز کردن تخصص خود هستید ، این راهنما شما را از متخصص بهینه سازی مبتدی به کارشناس می برد.
چرا بهینه سازی عملکرد اهمیت دارد
تصور کنید که ماراتن را اجرا می کنید. شما چکمه های سنگین نمی پوشید ، دنده های غیر ضروری را حمل می کنید ، یا از راه دور تصادفی استفاده می کنید ، درست است؟ به همین ترتیب ، در نرم افزار ، کد بهینه شده مانند اجرای ماراتن با چمدان های غیر ضروری است – این منابع را هدر می دهد ، کاربران را ناامید می کند و حتی می تواند هزینه های کسب و کار را نیز هزینه کند.
بهینه سازی عملکرد فقط مربوط به سریعتر کردن کد شما نیست. این در مورد ساختن آن است بهتربشر کد کارآمد از منابع کمتری استفاده می کند ، مقیاس های بهتری دارند و تجربه کاربری نرم و صاف تری را ارائه می دهند.
مرحله 1: پروفایل و معیار – قبل از بهینه سازی اندازه گیری کنید
قبل از اینکه بتوانید کد خود را سریعتر کنید ، باید مشخص کنید که تنگناها در کجا قرار دارند. به پروفایل به عنوان یک ابزار تشخیصی فکر کنید – به شما می گوید کدام قسمت از برنامه شما در حال کاهش سرعت است. از طرف دیگر ، معیار ، عملکرد کد شما را اندازه گیری می کند تا اطمینان حاصل شود که بهینه سازی های شما در واقع کار می کنند.
پروفایل با استودیو ویژوال
Visual Studio دارای یک پروفایل عملکرد داخلی است که باعث می شود تجزیه و تحلیل برنامه شما آسان شود. در اینجا نحوه استفاده از آن آورده شده است:
- پروژه خود را در ویژوال استودیو باز کنید.
- رفتن به اشکال زدایی> پروفایل عملکردبشر
- ابزارهای پروفایل مورد نیاز خود را انتخاب کنید ، مانند استفاده از CPU یا استفاده از حافظهبشر
- برنامه خود را اجرا کنید و داده های جمع آوری شده را تجزیه و تحلیل کنید.
پروفایل “نقاط داغ” را در کد شما برجسته می کند – منطقه ای که بیشترین پردازنده یا حافظه را مصرف می کند. این اهداف اصلی شما برای بهینه سازی است.
معیار با BenchmarkDotnet
در حالی که پروفایل تنگناها را مشخص می کند ، معیار عملکرد را تعیین می کند. کتابخانه BenchmarkDotnet یک استاندارد طلا برای معیار در .NET است.
در اینجا یک مثال ساده وجود دارد:
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
public class StringConcatenationBenchmark
{
private const int Iterations = 10000;
[Benchmark]
public string UsingPlusOperator()
{
string result = "";
for (int i = 0; i < Iterations; i++)
{
result += i;
}
return result;
}
[Benchmark]
public string UsingStringBuilder()
{
var builder = new System.Text.StringBuilder();
for (int i = 0; i < Iterations; i++)
{
builder.Append(i);
}
return builder.ToString();
}
}
public class Program
{
public static void Main(string[] args)
{
BenchmarkRunner.Run<StringConcatenationBenchmark>();
}
}
اینجا چه اتفاقی می افتد؟
-
UsingPlusOperator
: این روش رشته ها را با+
اپراتور -
UsingStringBuilder
: این روش از a استفاده می کندStringBuilder
برای هماهنگی ، که برای دستکاری های رشته ای بزرگ کارآمدتر است.
هنگامی که معیار را اجرا می کنید ، گزارش مفصلی را مشاهده می کنید که زمان اجرای هر روش را نشان می دهد. اسپویلر: StringBuilder
برای هماهنگی تکراری به طور قابل توجهی سریعتر است.
مرحله 2: تکنیک های بهینه سازی برای توسعه دهندگان C#
اکنون که می دانید چگونه مسائل مربوط به عملکرد را شناسایی کنید ، بیایید برخی از تکنیک های بهینه سازی را بررسی کنیم.
1 حلقه ها را بهینه کنید
حلقه ها منبع مشترک ناکارآمدی هستند. از محاسبات یا تخصیص غیر ضروری در حلقه ها خودداری کنید.
مثال: بهینه سازی حلقه
// Inefficient
for (int i = 0; i < collection.Count; i++)
{
Console.WriteLine(collection[i]);
}
// Optimized
int count = collection.Count;
for (int i = 0; i < count; i++)
{
Console.WriteLine(collection[i]);
}
چرا؟ در مثال اول ، collection.Count
در هر تکرار ارزیابی می شود. در نسخه بهینه سازی شده ، شمارش ذخیره می شود و عملیات اضافی را کاهش می دهد.
2 از بوکس و جعبه جعبه خودداری کنید
بوکس زمانی است که یک نوع مقدار (به عنوان مثال int
) به یک شی تبدیل می شود ، و بوکس زدن برعکس است. هر دو عمل از نظر محاسباتی گران هستند.
مثال: گودال بوکس
// Boxing occurs here
object boxed = 42;
// Unboxing occurs here
int unboxed = (int)boxed;
راه حل: برای جلوگیری از بوکس از ژنریک استفاده کنید.
public void PrintValue<T>(T value)
{
Console.WriteLine(value);
}
3 از برنامه نویسی ناهمزمان برای عملیات I/O استفاده کنید
مسدود کردن عملیات I/O می تواند به طور قابل توجهی بر عملکرد تأثیر بگذارد. استفاده کردن async
وت await
برای آزاد کردن موضوعات برای سایر کارها.
مثال: پرونده async خوانده شده است
using System.IO;
using System.Threading.Tasks;
public async Task<string> ReadFileAsync(string path)
{
using (var reader = new StreamReader(path))
{
return await reader.ReadToEndAsync();
}
}
4 تخصیص حافظه را به حداقل برسانید
تخصیص حافظه مکرر می تواند منجر به تکه تکه شدن و جمع آوری زباله ها شود. در صورت امکان از ترکیب شیء یا استفاده مجدد از اشیاء موجود استفاده کنید.
مثال: استخر شیء
using System.Buffers;
var pool = ArrayPool<int>.Shared;
// Rent an array of size 100
int[] array = pool.Rent(100);
// Use the array...
// Return the array to the pool
pool.Return(array);
مشکلات رایج (و نحوه جلوگیری از آنها)
حتی توسعه دهندگان باتجربه هنگام بهینه سازی کد در برخی از تله های مشترک قرار می گیرند. در اینجا چه چیزی را باید تماشا کنید:
1 بهینه سازی زودرس
کدی را که به آن احتیاج ندارد بهینه نکنید. تمرکز بر مناطقی که با پروفایل و معیار مشخص شده اند.
2 استفاده بیش از حد LINQ
در حالی که LINQ ظریف و بیانگر است ، گاهی اوقات می تواند سربار غیر ضروری را به ویژه در مسیرهای مهم و مهم اضافه کند.
مثال: linq در مقابل حلقه
// LINQ
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
// Loop
var evenNumbers = new List<int>();
foreach (var n in numbers)
{
if (n % 2 == 0)
evenNumbers.Add(n);
}
چرا؟ حلقه سریعتر است زیرا از سربار اجرای معوق و تخصیص اضافی جلوگیری می کند.
3 نادیده گرفتن جمع کننده زباله
جمع کننده زباله های NET (GC) کارآمد است ، اما تخصیص بیش از حد یا منابع می تواند چرخه های GC مکرر را ایجاد کند و باعث کاهش سرعت کاربرد شما شود. برای نظارت بر رفتار GC از ابزارهایی مانند Profiler Visual Studio Memory استفاده کنید.
غذاهای کلیدی و مراحل بعدی
- همیشه مشخصات اول: برای شناسایی تنگناها قبل از بهینه سازی از ابزارهایی مانند Profiler Visual Studio یا BenchmarkDotNet استفاده کنید.
- تجارت را درک کنید: بهینه سازی اغلب شامل تجارت بین خوانایی ، قابلیت حفظ و عملکرد است. فقط در جایی که مهم است بهینه سازی کنید.
- اتخاذ بهترین شیوه ها: از ساختار داده های کارآمد استفاده کنید ، تخصیص حافظه را به حداقل برسانید و از عملیات پر هزینه مانند بوکس/بوکس یا پرس و جوهای غیر ضروری LINQ خودداری کنید.
- آگاه باشید: اکوسیستم .NET به سرعت تکامل می یابد. به طور مرتب آخرین ویژگی ها و ابزارهای بهبود یافته را کشف کنید.
مراحل بعدی
- با نمونه های موجود در این پست وبلاگ آزمایش کنید و ببینید که چگونه آنها در مورد پروژه های شما اعمال می شوند.
- شیرجه عمیق تر به موضوعات پیشرفته مانند برنامه نویسی مبتنی بر دهانه (
Span
) ، Simd و موازی در .NET. - دستورالعمل های رسمی عملکرد .NET را کاوش کنید.
با تسلط به بهینه سازی عملکرد در C#، شما فقط نوشتن کد سریعتر نیستید – شما نرم افزار بهتری ایجاد می کنید. بنابراین ، پروفایل خود را آتش بزنید ، معیار را شروع کنید و بگذارید بهینه سازی ها شروع شود! برنامه نویسی مبارک! 🚀