C#، للحلقات، واختبار السرعة... نفس الحلقة بالضبط بشكل أسرع في المرة الثانية؟

StackOverflow https://stackoverflow.com/questions/303343

سؤال

public Int64 ReturnDifferenceA()
{
  User[] arrayList;
  Int64 firstTicks;
  IList<User> userList;
  Int64 secondTicks;
  System.Diagnostics.Stopwatch watch;

  userList = Enumerable
              .Range(0, 1000)
              .Select(currentItem => new User()).ToList();

  arrayList = userList.ToArray();

  watch = new Stopwatch();
  watch.Start();

  for (Int32 loopCounter = 0; loopCounter < arrayList.Count(); loopCounter++)
  {
     DoThings(arrayList[loopCounter]);
  }

  watch.Stop();
  firstTicks = watch.ElapsedTicks;

  watch.Reset();
  watch.Start();
  for (Int32 loopCounter = 0; loopCounter < arrayList.Count(); loopCounter++)
  {
     DoThings(arrayList[loopCounter]);
  }
  watch.Stop();
  secondTicks = watch.ElapsedTicks;

  return firstTicks - secondTicks;
}

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

الآن أنا أتصل مع هؤلاء:

differenceList = Enumerable
                 .Range(0, 50)
                 .Select(currentItem => ReturnDifferenceA()).ToList();
average = differenceList.Average();

differenceListA = Enumerable
                  .Range(0, 50)
                  .Select(currentItem => ReturnDifferenceA()).ToList();
averageA = differenceListA.Average();

differenceListB = Enumerable
                  .Range(0, 50)
                  .Select(currentItem => ReturnDifferenceA()).ToList();
averageB = differenceListB.Average();

الجزء الممتع الآن هو أن جميع المتوسطات إيجابية بمقدار كبير نسبيًا، يتراوح من 150 ألفًا إلى 300 ألف علامة.

ما لا أفهمه هو أنني أتصفح نفس القائمة، وبنفس الطريقة، وبنفس الطريقة، ومع ذلك يوجد مثل هذا الاختلاف.هل هناك نوع من التخزين المؤقت يحدث؟

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

هل كانت مفيدة؟

المحلول

وبالمناسبة، وذلك باستخدام IEnumerable.Count () على صفيف هو مئات المرات أبطأ من Array.Length ... على الرغم من هذا لا يجيب على السؤال على الإطلاق.

نصائح أخرى

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

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

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

فمن الممكن جدا أن DoThings () ليست JIT-ترجمة التعليمات البرمجية الأصلية حتى أول مرة يتم استدعاؤه.

لأن .NET، مثل منصة Java، هي بيئة JIT.يتم تجميع جميع أكواد .NET عالية المستوى إلى كود ثانوي للغة المتوسطة من Microsoft.

لتشغيل برنامجك، يجب تجميع/ترجمة هذا الرمز الثانوي إلى رمز الجهاز الأصلي.ومع ذلك، لا يتم تخزين ملفات .NET المبرمجة في كود الجهاز الأصلي ولكن في الكود الثانوي للجهاز الظاهري الوسيط.

تم تجميع التشغيل الأول بواسطة JIT، لذلك استغرق الأمر وقتًا إضافيًا.لم تعد عمليات التشغيل اللاحقة بحاجة إلى تجميع JIT، ولكن يتم سحب الكود الأصلي من ذاكرة التخزين المؤقت لـ JIT، لذا يجب أن يكون أسرع.

هل حافظت على طلبك دون الإنهاء في عمليات التشغيل اللاحقة؟ثم السبب الثاني يرجع أيضًا إلى VM.(VM:1 = جهاز افتراضي؛VM:2 = الذاكرة الظاهرية).تقوم جميع أنظمة التشغيل المعممة الحديثة بتشغيل عملياتها على الذاكرة الافتراضية، وهي عبارة عن خريطة للذاكرة الحقيقية، لتتيح لنظام التشغيل القدرة على إدارة موارد النظام وتحسين استخدامها.يتم في كثير من الأحيان نقل العمليات الأقل استخدامًا إلى ذاكرة التخزين المؤقت على القرص للسماح للعمليات الأخرى بالاستخدام الأمثل للموارد.

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

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

تسمح الآلة الافتراضية لـ .NET وJava بتجريد معظم ميزات البرمجة في طبقة مستقلة عن الآلة، مما يؤدي إلى فصلها وبالتالي ترك فوضى أصغر ليتعامل معها مهندسو البرمجيات المعتمدون على الآلة.على الرغم من أن نظام التشغيل Microsoft Windows يعمل على أجهزة موحدة إلى حد ما تعمل بنظام x86، إلا أن هناك اختلافات كافية مع إصدارات أنظمة التشغيل المختلفة ونماذج وحدة المعالجة المركزية (CPU) لضمان وجود جهاز ظاهري مجرد من أجل منح مبرمجي ومستخدمي .NET رؤية متسقة.

وأنت تقول أنك لا تحصل على أن يفعل ذلك 3 مرات، و2 والأوقات 3RD هي قريبة نسبيا. ويبدو لي أنه ليست سوى أول مرة من خلال الحلقة أن الأمور ما زالت بطيئة.

وكنت أظن أن وظيفة استدعاء ليست فقط في الوقت المناسب، حتى الجولة الأولى. ما يمكنك أن تجرب يتم تشغيله مرة واحدة، ثم وقفها وتشغيله مرة أخرى. ومع عدم وجود تغييرات رمز، وفقط في وقت يجمع من المدى السابق لا يزال ينبغي أن تكون على ما يرام، وأية تحسينات المتبقية ترى هي <م> الفعلي آثار التخزين المؤقت في العمل.

ونترك جانبا مسألة الاحماء VM أو آلة، التخزين المؤقت، من أمثل JIT، لحظة: ماذا يفعل جهاز الكمبيوتر الخاص بك؟ هل أي من خدمات النظام 3e42 وثينجيس صينية مهمة الاستيلاء على بعض وحدة المعالجة المركزية؟ ربما قرر العميل ستيم للتحقق من وجود تحديثات، أو IE يلزم القيام به شيء مهم مخيف، أو حصلت على برنامج مكافحة الفيروسات في الطريق؟

والاختبار الخاص بك هو مفيد مثل الدرجة التي يمكنك عزلها من جميع البرامج الأخرى التي تعمل على مربع فقط. إيقاف كل بت من البرامج يمكن لكم ربما قبل محاولة قياس المدى.

ولكن بعد ذلك ما أعرف؟ - ربما تدار طريقة القياس الخاص بك عن طريق صافي (أو أيا كان) وقت التشغيل للغاية ويمثل وقت التشغيل فقط "دورات الافتراضية '

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top