كيف أكتب (اختبار) رمز لن يكون الأمثل من خلال مترجم/JIT?

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

سؤال

أنا لا أعرف حقا الكثير عن دواخل مترجم و جيت التحسينات ، ولكن أنا عادة في محاولة استخدام "الحس السليم" إلى تخمين ما يمكن أن يكون الأمثل وما لا يمكن.لذا كنت أكتب وحدة بسيطة طريقة الاختبار اليوم:

@Test  // [Test] in C#
public void testDefaultConstructor() {
    new MyObject();
}

هذا الأسلوب هو في الواقع كل ما أحتاج.التحقق من أن منشئ افتراضي موجود ويعمل بدون استثناءات.

ولكن بعد ذلك بدأت أفكر تأثير مترجم/JIT التحسينات.يمكن أن المترجم/JIT تحسين هذا الأسلوب من خلال القضاء على new MyObject(); بيان تماما ؟ بالطبع, سوف تحتاج إلى تحديد هذا الرسم البياني الدعوة لا يكون لها آثار جانبية إلى كائنات أخرى ، وهي حالة نموذجية عادي منشئ ببساطة تهيئة الدولة الداخلي من وجوه.

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

ومع ذلك أنا أحاول التفكير في الموضوع العام.عندما فكرت في كيفية منع هذا الأسلوب من كونها الأمثل ، ظننت أنني قد assertTrue(new MyObject().toString() != null), ولكن هذا يعتمد جدا على التنفيذ الفعلي toString() طريقة و حتى ذلك الحين ، JIT يمكن تحديد toString() طريقة يعود دائما فارغة سلسلة (على سبيل المثالإذا فعلا Object.toString() يسمى) ، وبالتالي تحسين كل فرع.لذلك هذه الطريقة لا تعمل.

وأنا أعلم أن في C# يمكنني استخدام [MethodImpl(MethodImplOptions.NoOptimization)], ولكن ليس هذا ما أنا أبحث عن.أنا على أمل العثور على (لغة مستقلة) طريقة التأكد من أن بعض جزء معين(ق) من قانون بلدي سوف تعمل في الواقع كما أتوقع ، دون JIT التدخل في هذه العملية.

بالإضافة إلى ذلك, هل هناك أي نموذجية الأمثل الحالات يجب أن تكون على علم عند إنشاء وحدتي الاختبارات ؟

شكرا جزيلا!

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

المحلول

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

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

وتحرير: بالمناسبة، فإنه يمكن أيضا أن تكون ذكية بما فيه الكفاية لتحديد أن هذا الأسلوب:

newIfTrue(boolean b) {
    if(b)
        new ThisClass();
}

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

وهذا هو المكان الذي JIT يمكن أن تفعل الأشياء التي من المستحيل عمليا في أي لغة غير المدارة.

نصائح أخرى

واعتقد انه اذا كنت قلقا حيال ذلك الحصول الأمثل بعيدا، هل يمكن أن تفعل شيئا من الاختبار مبالغة.

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

وأنا أعرف أن هناك أناسا لا تتفق معي، لكنني أشعر أن هذا النوع من الشيء هو مجرد شيء من شأنها أن تشعر بالانتفاخ من رقمك من الاختبارات من دون سبب مفيد، حتى النظر اليها من خلال نظارات TDD.

وفكروا بهذه الطريقة:

لنفترض أن المترجم يمكن تحديد أن الرسم البياني الدعوة ليس لديها أي آثار جانبية (لا أعتقد أنه من الممكن، أتذكر غامضة شيئا عن P = NP من وجهة نظري CS دورات). وسوف تحسين أي الطريقة التي لا يكون لها آثار جانبية. وبما أن معظم التجارب لم يكن لديك ويجب أن لا يكون أي آثار جانبية ثم مترجم يمكن تحسين كل منهم بعيدا.

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

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

PS:علما أن هذا ينطبق لأنك تفعل وظائف اختبار بدلا الأداء الاختبار.في اختبار الأداء ، من المهم التأكد من JIT لا تحسين بعيدا العملية يتم قياس آخر النتائج الخاصة بك تصبح عديمة الفائدة.

ويبدو أن في C # أتمكن من القيام بذلك:

[Test]
public void testDefaultConstructor() {
    GC.KeepAlive(new MyObject());
}

وAFAIU، لن inlined طريقة GC.KeepAlive من قبل JIT، لذلك سوف تكون مضمونة رمز للعمل كما هو متوقع. ومع ذلك، وأنا لا أعرف مفهوما مشابها في جاوة.

وماذا يجب أن يهم؟ إذا كان المترجم / JIT يمكن تحديد بشكل ثابت لا يؤكد على وشك أن تضرب (والتي يمكن أن تتسبب في آثار جانبية)، ثم كنت على ما يرام.

وكل I / O هو أحد الآثار الجانبية، حتى تتمكن من وضع فقط

Object obj = new MyObject();
System.out.println(obj.toString());

وأنت بخير.

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