هل يؤدي استخدام السياق غير المحدد إلى الإضرار بالأداء أو قابلية النقل في ج#?

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

سؤال

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

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

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

المحلول

من الناحية الفنية فقط checked يجب أن تبطئ الكتل.لذلك أنا لا أعتقد أن unchecked كتلة (كتلة حيث الإطار يجب أن تفعل أقل الشيكات) يمكن أن تبطئ.إنه ليس مفتاح سياق أو شيء مشابه.جيت ببساطة لا تنبعث منها تعليمات للتحقق من تجاوز / تحت التدفق.الآن ، من الواضح إذا كان شخص ما خلق معالج" خاص " حيث يجب محاكاة تجاوز واستدار أحادية على ذلك ، أو حيث تجاوز يسبب نتائج مختلفة من على معالجات إنتل ، و unchecked كتلة سيكون أبطأ (لأن جيت يجب أن "محاكاة" ذلك).ولكن لاحظ أن أنواع قاعدة صافي يتم تعريفها في إسما قياسي.يجب أن تستند السجلات الموقعة إلى مكملين على سبيل المثال ، ويجب أن يكون حجمها 8 ، 16 ، 32 ، 64 بت.لا توجد مساحة كبيرة للمعالجات "الغريبة" التي تستخدم 36 بت الأعداد الصحيحة.

نصائح أخرى

فحص إضافة تعليمات عملية واحدة فقط:

checked
{
    int y = x * x;
05297978  mov         eax,dword ptr [ebp-10h]  
0529797B  imul        eax,dword ptr [ebp-10h]  
0529797F  jno         05297986  //if not overflow: goto 05297986
05297981  call        72A29522  //invoke exception
05297986  mov         dword ptr [ebp-14h],eax  
}

unchecked
{
    int yy = xx * xx;
0529799E  mov         eax,dword ptr [ebp-18h]  
052979A1  imul        eax,dword ptr [ebp-18h]  
052979A5  mov         dword ptr [ebp-1Ch],eax  
}

وكقاعدة عامة يمكنك أن تتوقع الحساب دون رادع ليكون أسرع قليلا ، لكنه الى حد كبير لا يستحق طرح السؤال المعاكس لك (بمعنى."سوف باستخدام فحص يضر أدائي?").

فحص ودون رادع يعني فقط أن هناك قواعد مختلفة قليلا عن كيفية مثل المشغلين +, *, ، و - يتم التعامل معها ، ويجب عليك استخدام واحد مناسب للحالة في متناول اليد.

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

لقد أنشأت طريقتين ، واحدة ملفوفة بواسطة checked وآخر من قبل unchecked.من خلال النظر في ايل فرق واحد فقط هو mul العملية (التي تقوم بعملية الضرب) ، لفحصها mul.ovf يتم إنشاؤه ولم يتم التحقق منه - mul.

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

مسن:

تعليمات اللغة المتوسطة التالية من ميكروسوفت (مسيل) رمي أوفيرفلوكسيبتيون:

  • مول.عوف.
  • ...
[Test]
public void Checked()
{
    checked
    {
        int i = int.MaxValue;
        i = i * 100;
        Debug.WriteLine(i);
    }
}

[Test]
public void UnChecked()
{
    unchecked
    {
        int i = int.MaxValue;
        i = i * 100;
        Debug.WriteLine(i);
    }            
}

ثم باستخدام إلداسم انظر إيل:

فحص():

// Code size       27 (0x1b)
  .maxstack  2
  .locals init ([0] int32 i)
  IL_0000:  nop
  IL_0001:  nop
  IL_0002:  ldc.i4     0x7fffffff
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  ldc.i4.s   100
  **IL_000b:  mul.ovf** !!!
  IL_000c:  stloc.0
  IL_000d:  ldloc.0
  IL_000e:  box        [mscorlib]System.Int32
  IL_0013:  call       void [System]System.Diagnostics.Debug::WriteLine ...

غير محدد():

  // Code size       27 (0x1b)
  .maxstack  2
  .locals init ([0] int32 i)
  IL_0000:  nop
  IL_0001:  nop
  IL_0002:  ldc.i4     0x7fffffff
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  ldc.i4.s   100
  **IL_000b:  mul** !!!
  IL_000c:  stloc.0
  IL_000d:  ldloc.0
  IL_000e:  box        [mscorlib]System.Int32
  IL_0013:  call       void [System]System.Diagnostics.Debug::WriteLine(...)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top