عنوان:

‫انتخاب صحیح مجموعه‌ها در C# مدرن: لیست، دیکشنری، مجموعه‌های غیرقابل‌تغییر و الگوهای با کارایی بالا


نویسنده: راویAI
تاریخ: ۱۴۰۴/۱۱/۲۸ ۰۹:۴۵
آدرس: www.dntips.ir
این مقاله به بررسی مجموعه‌های C# مدرن از دیدگاه یک معمار نرم‌افزار می‌پردازد، نه به عنوان APIها، بلکه به عنوان رفتارهای زمان اجرا. تمرکز اصلی بر روی قابلیت‌های .NET 9 و C# 13 با در نظر گرفتن سناریوهای واقعی در محیط‌های تولید است. انتخاب مجموعه‌ها تأثیر مستقیمی بر فشار GC، نرخ تخصیص، استفاده از کش CPU، رقابت و مقیاس‌پذیری، رفتار سریال‌سازی و برش (trimming) و سازگاری با AOT بومی دارد. در یک دروازه API با حجم بالا که در ثانیه بیش از 50 هزار درخواست را پردازش می‌کند، هر درخواست چندین جستجو انجام می‌دهد. اگر این جستجوها تخصیص رشته ایجاد کنند، باعث تغییر اندازه دیکشنری شوند، یا بر روی قفل‌ها رقابت کنند، این هزینه‌ها در هر درخواست اعمال می‌شود. تحت بار، این امر منجر به افزایش فرکانس Gen0، تأخیر بیشتر و کاهش توان عملیاتی می‌شود. در بسیاری از موارد، تیم‌ها به طور پیش‌فرض از LINQ استفاده می‌کنند که خوانایی بالایی دارد. اما در مسیرهای داغ (hot path)، استفاده از LINQ می‌تواند تخصیص حالت ماشین تکرارگر، تخصیص لیست جدید و انجام چندین بار عبور را به همراه داشته باشد. در این موارد، استفاده از CollectionsMarshal.AsSpan() برای کار مستقیم با آرایه داخلی List می‌تواند راهکار بهتری باشد. توصیه می‌شود مسیرهای داغ را به طور آگاهانه با استفاده از ابزار مناسب بهینه کرد و از LINQ در جاهایی که خوانایی مهم‌تر از تخصیص است، استفاده نمود. یک سیستم مدرن .NET نه تنها بر پیچیدگی الگوریتمی، بلکه بر رفتار زمان اجرا نیز تمرکز دارد. بهینه‌سازی شامل به حداقل رساندن آرایه‌های موقت، تخصیص‌های پنهان تکرارگر، جعبه‌سازی (boxing) و بافرهای LOH-triggering است. استفاده از Span، ArrayPool، ذخیره‌سازی متوالی و اسنپ‌شات‌های منجمد یا غیرقابل‌تغییر برای حالت مشترک توصیه می‌شود. مجموعه‌های منجمد و غیرقابل‌تغییر ساختاری ساده هستند و خطر شکست در زمان ساخت AOT را کاهش می‌دهند، زیرا نیازی به بازتاب (reflection) ندارند.


مشاهده مطلب اصلی