سؤال

أنا أعمل حاليا على برامج الشبكة.لديها فئة رئيسية واحدة، server والذي يمثل بوضوح مثيل الخادم.

أ server يمكن للمثيل إرسال طلبات ويتم إخطار المستخدم بالاستجابة من خلال رد اتصال.

الكود مثل:

class server
{
  public:
    typedef boost::function<void (int duration)> callback_func;

    void send_request(endpoint& ep, callback_func cb);
};

الآن لنفترض أنه كمستخدم أريد أن أعرف رد الاتصال عن المثيل الذي استدعاه، يمكنني القيام بالشيء التالي:

void mycallback(const server& sv, int duration) { ... }

server sv;
sv.send_request("localhost", boost::bind(&mycallback, boost::ref(sv), _1));

لكن انا اتسائل:هل هناك أي النفقات العامة للقيام بذلك؟سوف المكالمات إلى mycallback هل تكون أبطأ من استخدام مكالمة "عادية"؟

شكرًا لك.

هامش:يمكنني بالطبع تغيير رأيي typedef ل: typedef boost::function<void (const server& sv, int duration)> callback_func; و إذا boost::bind تسبب أي نفقات كبيرة، وهذا على الأرجح ما سأفعله في النهاية.أود فقط أن أعرف ما هي التكاليف التي تنطوي على استخدام boost::bind.

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

المحلول

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

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

نصائح أخرى

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

ملاحظة.وأنا أتفق مع تاماس سزيلي:تقديم 10 ملايين طلب وقياسها.

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

يرجع السبب غير المباشر الأول إلى محو النوع الذي يحدث في Boost::function (وهذا هو موثقة في ال boost::function توثيق).لا يمكن تحسين هذا الخيار حقًا، وستحصل على نفس العقوبة باستخدام مؤشر دالة مجردة أيضًا.

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

بدلاً من

void mycallback( .1. ) { .2. }

أنت تفعل

struct mycallback {
    void operator()( .1. ) const { .2. }
};

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

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