سؤال

قبل قراءة السؤال:
هذا السؤال لا يتعلق بمدى فائدة استخدامه dynamic_cast. انها فقط عن أدائها.

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

قررت اختبار أداء هذه الطريقة بدلاً من مجرد تصديقها.

تم استخدام الرمز التالي:

ptime firstValue( microsec_clock::local_time() );

ChildObject* castedObject = dynamic_cast<ChildObject*>(parentObject);

ptime secondValue( microsec_clock::local_time() );
time_duration diff = secondValue - firstValue;
std::cout << "Cast1 lasts:\t" << diff.fractional_seconds() << " microsec" << std::endl;

يستخدم الرمز أعلاه الطرق من boost::date_time على Linux للحصول على قيم قابلة للاستخدام.
لقد فعلت 3 dynamic_cast في تنفيذ واحد ، رمز قياسها هو نفسه.

كانت نتائج التنفيذ 1 هي ما يلي:
Cast1 يدوم: 74 microsec
Cast2 يدوم: 2 microsec
Cast3 يدوم: 1 microsec

استغرق أول فريق الممثلين دائمًا 74-111 microsec ، حيث استغرق الأمر التالي في نفس الإعدام 1-3 microsec.

لذلك أخيرًا أسئلتي:
هو dynamic_cast حقا أداء سيء؟
وفقا ل testresults انها لا. هل رمز testcode الخاص بي صحيح؟
لماذا يعتقد الكثير من المطورين أنه بطيء إذا لم يكن كذلك؟

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

المحلول

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

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

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

أعلم أنك لا تريد التحدث عن هذا ، ولكن "تصميم حيث يتم استخدام Dynamic_cast كثيرًا" هو مؤشر على أنك تفعل شيئًا خاطئًا ...

نصائح أخرى

الأداء لا معنى له دون مقارنة الوظائف المكافئة. يقول معظم الناس أن Dynamic_cast بطيئة دون مقارنة السلوك المكافئ. اتصل بهم على هذا. ضع طريقا اخر:

إذا لم يكن "يعمل" شرطًا ، فيمكنني كتابة رمز يفشل بشكل أسرع من لك.

هناك طرق مختلفة لتنفيذ Dynamic_cast ، وبعضها أسرع من غيرها. نشر Stroustrup ورقة حول استخدام الأعداد الأولية لتحسين Dynamic_cast, ، فمثلا. لسوء الحظ ، من غير المعتاد التحكم في كيفية تنفيذ برنامج التحويل البرمجي الخاص بك ، ولكن إذا كان الأداء مهمًا لك حقًا ، فأنت تتحكم في أي برنامج التحويل البرمجي الذي تستخدمه.

لكن، عدم استخدام will dynamic_cast دائماً كن أسرع من استخدامه - ولكن إذا كنت لا تحتاج فعليًا إلى Dynamic_cast ، فلا تستخدمه! إذا كنت بحاجة إلى بحث ديناميكي ، فسيكون هناك بعض النفقات العامة ، ويمكنك بعد ذلك مقارنة الاستراتيجيات المختلفة.

فيما يلي بعض المعايير:
http://tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance/
http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html

وفقًا لهم ، يكون Dynamic_cast أبطأ 5-30 مرات من RENINTPREPRET_CAST ، ويقوم أفضل بديل تقريبًا بنفس القدر مثل reinterpret_cast.

سأقتبس من الاستنتاج من المقال الأول:

  • Dynamic_cast بطيئة لأي شيء سوى صب إلى النوع الأساسي ؛ تم تحسين هذا الممثل الخاص
  • مستوى الميراث له تأثير كبير على Dynamic_cast
  • متغير العضو + REINTERPRET_CAST هو أسرع طريقة موثوقية ل
    تحديد النوع ؛ ومع ذلك ، فإن هذا يحتوي على نفقات صيانة أعلى بكثير
    عند الترميز

الأرقام المطلقة في حدود 100 نانو ثانية لممثلين واحد. قيم مثل 74 MSEC لا تبدو قريبة من الواقع.

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

ليس هناك شك الكود للذهاب وفحص الكائن لتحديد نوعه الحقيقي.

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

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