الأداء في .NET Core

الأداء في .NET Core


صورة

مرحبا بالجميع! هذه المقالة عبارة عن مجموعة من أفضل الممارسات ، والتي كنت أنا وزملائي نستخدمها لفترة طويلة عند العمل في مشاريع مختلفة.

معلومات حول الجهاز الذي تم إجراء العمليات الحسابية عليه:
BenchmarkDotNet = v0.11.5 ، OS = Windows 10.0.18362
Intel Core i5-8250U CPU 1.60 جيجاهرتز (Kaby Lake R) ، وحدة المعالجة المركزية 1 ، 8 النوى المنطقية و 4 النوى المادية
.NET Core SDK = 3.0.100
[المضيف]: .NET Core 2.2.7 (CoreCLR 4.6.28008.02 ، CoreFX 4.6.28008.03) ، 64 بت RyuJIT
Core: .NET Core 2.2.7 (CoreCLR 4.6.28008.02 ، CoreFX 4.6.28008.03) ، 64 بت RyuJIT
[المضيف]: .NET Core 3.0.0 (CoreCLR 4.700.19.46205 ، CoreFX 4.700.19.46214) ، 64 بت RyuJIT
Core: .NET Core 3.0.0 (CoreCLR 4.700.19.46205 ، CoreFX 4.700.19.46214) ، 64 بت RyuJIT

الوظيفة = وقت التشغيل الأساسي = الأساس

ToList مقابل ToArray والدورات


لقد خططت لإعداد هذه المعلومات مع إصدار .NET Core 3.0 ، لكنهم سبقوني ، لا أريد سرقة شهرة شخص آخر ونسخ معلومات شخص آخر ، لذلك سأشير فقط إلى رابط لمقال جيد يتم فيه تفصيل المقارنة .

من نفسي ، أريد فقط أن أقدم لكم قياساتي ونتائجي ، أضفت لهم حلقات عكسية لمحبي "نمط C ++" لحلقات الكتابة.

الرمز:
public class Bench { private List<int> _list; private int[] _array; [Params(100000, 10000000)] public int N; [GlobalSetup] public void Setup() { const int MIN = 1; const int MAX = 10; Random random = new Random(); _list = Enumerable.Repeat(0, N).Select(i => random.Next(MIN, MAX)).ToList(); _array = _list.ToArray(); } [Benchmark] public int ForList() { int total = 0; for (int i = 0; i < _list.Count; i++) { total += _list[i]; } return total; } [Benchmark] public int ForListFromEnd() { int total = 0;t for (int i = _list.Count-1; i > 0; i--) { total += _list[i]; } return total; } [Benchmark] public int ForeachList() { int total = 0; foreach (int i in _list) { total += i; } return total; } [Benchmark] public int ForeachArray() { int total = 0; foreach (int i in _array) { total += i; } return total; } [Benchmark] public int ForArray() { int total = 0; for (int i = 0; i < _array.Length; i++) { total += _array[i]; } return total; } [Benchmark] public int ForArrayFromEnd() { int total = 0; for (int i = _array.Length-1; i > 0; i--) { total += _array[i]; } return total; } } 


الأداء في .NET Core 2.2 و 3.0 متطابقان تقريبًا. إليك ما تمكنت من الحصول عليه في .NET Core 3.0:





يمكننا أن نستنتج أن معالجة الحلقة لمجموعة من النوع Array أسرع ، بسبب التحسينات الداخلية والتخصيص الواضح لحجم المجموعة. من الجدير أيضًا أن نتذكر أن مجموعة أنواع القائمة لها مزاياها ويجب عليك استخدام المجموعة المطلوبة وفقًا للحسابات اللازمة. حتى لو كتبت منطق العمل مع الدورات ، لا تنسَ أن هذه حلقة عادية وأنها أيضًا عرضة للتحسين المحتمل للدورات. ظهر مقال عن هابر لفترة طويلة: https://habr.com/en/post/124910/ . أنها لا تزال ذات صلة وأوصت للقراءة.

رمي


قبل عام ، كنت أعمل في شركة في مشروع قديم ، في ذلك المشروع ، كان من الطبيعي أن نتعامل مع التحقق من صحة الحقل من خلال بنية اختبار جذابة. لقد فهمت بالفعل أن هذا كان منطقًا تجاريًا غير صحي للمشروع ، لذلك حاولت عدم استخدام هذا التصميم إذا أمكن ذلك. ولكن دعونا نرى ما هو النهج السيئ للتعامل مع الأخطاء مع مثل هذا التصميم. كتبت رمزًا صغيرًا لمقارنة المقاربتين واطلاق النار على "المقاعد" لكل خيار.

الرمز:
  public bool ContainsHash() { bool result = false; foreach (var file in _files) { var extension = Path.GetExtension(file); if (_hash.Contains(extension)) result = true; } return result; } public bool ContainsHashTryCatch() { bool result = false; try { foreach (var file in _files) { var extension = Path.GetExtension(file); if (_hash.Contains(extension)) result = true; } if(!result) throw new Exception("false"); } catch (Exception e) { result = false; } return result; } 


النتائج في .NET Core 3.0 و Core 2.2 لها نتيجة مماثلة (.NET Core 3.0):





حاول التقاط تعقيد فهم التعليمات البرمجية وزيادة وقت تنفيذ البرنامج. ولكن إذا كنت بحاجة إلى هذا الإنشاء ، فلا ينبغي عليك إدراج سطور التعليمات البرمجية التي لا يُتوقع منها معالجة الأخطاء - فهذا سيسهل فهم الشفرة. في الواقع ، ليس معالجة الاستثناءات هي التي تقوم بتحميل النظام بقدر ما يتم طرح الأخطاء بنفسها عبر إنشاء استثناء جديد.

استثناءات الرمي أبطأ من أي فئة تجمع خطأً في التنسيق المطلوب. إذا كنت تقوم بمعالجة نموذج أو أي بيانات وتعرف بوضوح ما الخطأ الذي يجب أن يكون ، فلماذا لا تقوم بمعالجته؟

يجب أن لا تكتب رمي استثناء جديد () إذا كان هذا الموقف غير استثنائي. معالجة ورمي استثناء مكلفة للغاية !!!

ToLower ، ToLowerInvariant ، ToUpper ، ToUpperInvariant


على مدار 5 سنوات من الخبرة في نظام .NET الأساسي ، قابل العديد من المشروعات التي تستخدم مطابقة السلاسل. رأيت أيضًا الصورة التالية: كان هناك حل واحد للمؤسسات يحتوي على العديد من المشروعات ، أجرى كل منها مقارنات سلسلة بطرق مختلفة. ولكن ما الذي يستحق الاستخدام وكيفية توحيده؟ في Richter’s CLR عبر C # ، قرأت أن ToUpperInvariant () أسرع من ToLowerInvariant ().

قصاصة من الكتاب:



بالطبع ، لم أصدق ذلك وقررت إجراء بعض الاختبارات مرة أخرى على .NET Framework والنتيجة صدمتني - زيادة الأداء بنسبة تزيد على 15٪. بعد وصولي إلى العمل في صباح اليوم التالي ، أظهرت هذه القياسات لرؤسائي ومنحتهم إمكانية الوصول إلى المصدر. بعد ذلك ، تم تغيير مشروعين من بين 14 مشروعًا لقياسات جديدة ، وبالنظر إلى وجود هذين المشروعين لمعالجة جداول إكسل ضخمة ، فإن النتيجة كانت أكثر أهمية بالنسبة للمنتج.

أقدم لك أيضًا قياسات لإصدارات مختلفة من .NET Core ، حتى يتسنى لكل منكما الاختيار في اتجاه الحل الأمثل. وأريد فقط إضافة ذلك في الشركة التي أعمل فيها ، نستخدم ToUpper () لمقارنة السلاسل.

الرمز:
 public const string defaultString = "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3"; [Benchmark] public bool ToLower() { return defaultString.ToLower() == defaultString.ToLower(); } [Benchmark] public bool ToLowerInvariant() { return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant(); } [Benchmark] public bool ToUpper() { return defaultString.ToUpper() == defaultString.ToUpper(); } [Benchmark] public bool ToUpperInvariant() { return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant(); } . public const string defaultString = "VXTDuob5YhummuDq1PPXOHE4PbrRjYfBjcHdFs8UcKSAHOCGievbUItWhU3ovCmRALgdZUG1CB0sQ4iMj8Z1ZfkML2owvfkOKxBCoFUAN4VLd4I8ietmlsS5PtdQEn6zEgy1uCVZXiXuubd0xM5ONVZBqDu6nOVq1GQloEjeRN8jXrj0MVUexB9aIECs7caKGddpuut3"; [Benchmark] public bool ToLower() { return defaultString.ToLower() == defaultString.ToLower(); } [Benchmark] public bool ToLowerInvariant() { return defaultString.ToLowerInvariant() == defaultString.ToLowerInvariant(); } [Benchmark] public bool ToUpper() { return defaultString.ToUpper() == defaultString.ToUpper(); } [Benchmark] public bool ToUpperInvariant() { return defaultString.ToUpperInvariant() == defaultString.ToUpperInvariant(); } 






في .NET Core 3.0 ، يكون الربح لكل طريقة من هذه الطرق هو x2 ويوازن بين التطبيقات فيما بينها.





تجميع الطبقة


في مقالتي الأخيرة وصفت هذه الوظيفة لفترة وجيزة ، وأود أن تصحيح واستكمال كلماتي. يعمل التصنيف متعدد المستويات على تسريع وقت إطلاق الحل الخاص بك ، لكنك تضحي بأن أجزاء من التعليمات البرمجية الخاصة بك ستترجم إلى إصدار أكثر تحسينًا في الخلفية ، مما قد يؤدي إلى حمل صغير. مع ظهور NET Core 3.0 ، تم تقليل وقت إنشاء المشروعات ذات التجميع الطبقي والإصلاحات الثابتة المتعلقة بهذه التقنية. سابقًا ، أدت هذه التقنية إلى حدوث أخطاء في الطلبات الأولى في ASP.NET Core وتجمدت أثناء الإنشاء الأول في وضع التحويل البرمجي متعدد المستويات. حاليًا ، يتم تمكينه افتراضيًا في .NET Core 3.0 ، ولكن يمكنك تعطيله حسب الرغبة. إذا كنت في موقع قيادة فريق ، أو كبير ، أو متوسط ​​، أو كنت رئيس القسم ، فيجب أن تفهم أن التطوير السريع للمشروع يزيد من قيمة الفريق وأن هذه التكنولوجيا ستتيح لك توفير وقت المطورين ووقت عمل المشروع.

مستوى الصافي


قم بترقية .NET Framework / .NET Core. في كثير من الأحيان ، يعطي كل إصدار جديد دفعة إضافية للأداء ويضيف ميزات جديدة.

ولكن ما هي بالضبط الفوائد؟ لنلقِ نظرة على بعضهم:

  • في .NET Core 3.0 ، تم تقديم صور R2R تقلل من وقت بدء تشغيل تطبيقات .NET Core.
  • تم تقديم الإصدار 2.2 من Tier Compilation ، وذلك بفضل المبرمجين الذين سيقضون وقتًا أقل في إطلاق المشروع.
  • دعم .NET قياسي جديد.
  • دعم الإصدار الجديد من لغة البرمجة.
  • التحسين ، مع كل إصدار جديد ، يتم تحسين التحسين بواسطة مجموعة المكتبات الأساسية / البنية / الدفق / السلسلة / Regex وأكثر من ذلك بكثير. إذا قمت بالترقية من .NET Framework إلى .NET Core ، فستحصل على دفعة كبيرة من الأداء. على سبيل المثال ، أرفق ارتباطًا إلى جزء من التحسينات التي تمت إضافتها في .NET Core 3.0: https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/



استنتاج


عند كتابة التعليمات البرمجية ، يجب الانتباه إلى جوانب مختلفة من مشروعك واستخدام وظائف لغة البرمجة ومنصة لتحقيق أفضل نتيجة. سأكون سعيدًا إذا كنت تشارك معلوماتك المتعلقة بالتحسين في .NET.

رابط جيثب

Source: https://habr.com/ru/post/ar474800/


All Articles