في C# هل هناك أي أهمية الفارق في الأداء باستخدام UInt32 مقابل Int32

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

  •  08-07-2019
  •  | 
  •  

سؤال

أنا ترقية تطبيق موجود على C# و ترغب في تحسين الأداء كلما كان ذلك ممكنا.كثير من القائمة حلقة عدادات مجموعة المراجع بأنها النظام.UInt32 بدلا من Int32 كنت قد استخدمت.

هل هناك أي أهمية الفارق في الأداء باستخدام UInt32 مقابل Int32?

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

المحلول

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

والفرق الأكبر هو في الامتثال CLS كما في الأنواع غير موقعة ليست متوافقة مع CLS وليس كل اللغات تدعمهم.

نصائح أخرى

الجواب القصير هو "لا.أي تأثير الأداء ستكون ضئيلة".

الجواب الصحيح هو "ذلك يعتمد".

أفضل السؤال هو "هل يجب استخدام uint عندما أنا متأكد من أني لا تحتاج إلى علامة؟"

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

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

أفضل طريقة للإجابة على هذه الأسئلة هو تشغيل الاختبار.

class Program
{
  static void Main(string[] args)
  {
    const int iterations = 100;
    Console.WriteLine($"Signed:      {Iterate(TestSigned, iterations)}");
    Console.WriteLine($"Unsigned:    {Iterate(TestUnsigned, iterations)}");
    Console.Read();
  }

  private static void TestUnsigned()
  {
    uint accumulator = 0;
    var max = (uint)Int32.MaxValue;
    for (uint i = 0; i < max; i++) ++accumulator;
  }

  static void TestSigned()
  {
    int accumulator = 0;
    var max = Int32.MaxValue;
    for (int i = 0; i < max; i++) ++accumulator;
  }

  static TimeSpan Iterate(Action action, int count)
  {
    var elapsed = TimeSpan.Zero;
    for (int i = 0; i < count; i++)
      elapsed += Time(action);
    return new TimeSpan(elapsed.Ticks / count);
  }

  static TimeSpan Time(Action action)
  {
    var sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.Elapsed;
  }
}

اثنين من طرق الاختبار ، TestSigned و TestUnsigned, كل إجراء ~2 مليون التكرار بسيط زيادة على الموقعة وغير صحيح ، على التوالي.اختبار الكود يعمل 100 التكرارات لكل اختبار المتوسطات النتائج.هذا ينبغي أن تخلص من أي تناقضات محتملة.النتائج على i7-5960X جمعت x64 هي:

Signed:      00:00:00.5066966

Unsigned:    00:00:00.5052279

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

Bytecode

هنا يمكننا أن نرى أن C# compiler تفضل وقعت الاعداد الصحيحه و ينفذ فعلا معظم العمليات أصلا كما وقعت الصحيحه فقط من أي وقت مضى يعامل القيمة في الذاكرة كما موقعة عند مقارنة فرع (a.ك.القفز أو إذا).على الرغم من أننا استخدام صحيح غير الموقعة لكل مكرر و تراكم في TestUnsigned, الرمز هو مطابق تقريبا TestSigned طريقة باستثناء واحدة التعليمات: IL_0016.نظرة سريعة على ECMA المواصفات توضح الفرق:

blt.الأمم المتحدة.s :فرع لاستهداف إذا كانت أقل من (غير موقعة أو غير مرتبة), شكل قصيرة.

blt.s :فرع الهدف إذا كان أقل من النموذج القصير.

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

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

إذن إذا كان الأداء غير متطابقة ، السؤال المنطقي التالي هو: "هل يجب استخدام غير موقعة قيمة عندما أنا على يقين لا تحتاج علامة؟"

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

TLDR; في C++ أيام ، أود أن أقول "استخدام كل ما هو أنسب والسماح مترجم نوعا ما عن بقية الناس." C# ليست تماما كما قص الجافة, لذلك أود أن أقول هذا .صافي:هناك حقا أي الفارق في الأداء بين الموقعة وغير صحيح على x86/x64, ولكن معظم العمليات تتطلب توقيع عدد صحيح إلا إذا كنت حقا بحاجة إلى تقييد القيم الإيجابية فقط أو كنت حقا بحاجة اضافية تتراوح أن علامة بت يأكل العصا مع توقيع عدد صحيح.التعليمات البرمجية الخاصة بك وسوف تكون أكثر نظافة في نهاية المطاف.

وأنا لم تفعل أي بحث بشأن هذه المسألة في .NET، ولكن في الأيام الخوالي من فيروس Win32 / C ++، إذا أردت أن يلقي "الباحث قعت" إلى "وقعت منذ فترة طويلة"، وكان وحدة المعالجة المركزية لتشغيل المرجع لتوسيع علامة. ليلقي "صحيح غير الموقعة" إلى "غير موقعة طويل"، وكان مجرد الاشياء صفر في البايت العليا. وكانت المدخرات بناء على أمر من اثنين من دورات ساعة (أي عليك أن تفعل ذلك المليارات من المرات أن يكون هناك اختلاف حتى فهمه)

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

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

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

وهذا ليس حقا أن تفعل مع الأداء بدلا متطلبات العداد حلقة.

وPrehaps كان هناك الكثير من التكرار لاستكمال

        Console.WriteLine(Int32.MaxValue);      // Max interation 2147483647
        Console.WriteLine(UInt32.MaxValue);     // Max interation 4294967295

قد يكون صحيح غير الموقعة هناك لسبب ما.

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