بيانات تكلفة التخزين المؤقت في C ++ - احصائيات-راقب وظيفة مقابل المتغيرات عضو قابلة للتغيير

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

سؤال

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

double AdjustData(double d, int key) const {
  double factor = LongRunningOperationToFetchFactor(key);
  return factor * d;
}

وأود AdjustData أن تبقى const، ولكن أريد أن تخزين من عامل لذلك أنا فقط جلب هذه هي المرة الأولى. في الوقت الحاضر أنا باستخدام mutable map<int, double> لتخزين نتيجة (خريطة يجري من key إلى factor)، ولكن أنا أفكر باستخدام ساكنة راقب وظيفة قد يكون أفضل حل - هناك حاجة إلى هذا العامل إلا من خلال هذه الوظيفة، وغير لا علاقة لبقية الطبقة.

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

شكرا،

ودوم

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

المحلول

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

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <map>

using namespace std;

static boost::mutex myMutex;
static map<int,double> results;

double CachedLongRunningOperationToFetchFactor( int key )
{

   {
       boost::mutex::scoped_lock lock(myMutex);

       map<int,double>::iterator iter = results.find(key);
       if ( iter != results.end() )
       {
          return (*iter).second;
       }
   }
   // not in the Cache calculate it
   result = LongRunningOperationToFetchFactor( key );
   {
       // we need to lock the map again
       boost::mutex::scoped_lock lock(myMutex);
       // it could be that another thread already calculated the result but
       // map assignment does not care.
       results[key] = result;
   }
   return result;
}

وإذا كان هذا هو حقا عملية تشغيلها لفترة طويلة ثم تكلفة تأمين المزامنة يجب أن يكون الحد الأدنى.

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

نصائح أخرى

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

وكما قلت يجب أن تكون ذات ألوان - إذا المواضيع المختلفة يمكن استدعاء الدالة العضو على نفس الكائن، وربما كنت ترغب في استخدام مزامنة. boost::thread هي مكتبة جيدة لاستخدامها.

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

#include <cstdlib>
#include <iostream>
#include <map>

using namespace std;

class FactorMaker {
    map<int, double> cache;

    double longRunningFetch(int key)
    {
        const double factor = static_cast<double> (rand()) / RAND_MAX;
        cout << "calculating factor for key " << key << endl;
        // lock
        cache.insert(make_pair(key, factor));
        // unlock
        return factor;
    }

public:
    double getFactor(int key) {
        // lock
        map<int, double>::iterator it = cache.find(key);
        // unlock
        return (cache.end() == it) ? longRunningFetch(key) : it->second;
    }
};

FactorMaker & getFactorMaker()
{
    static FactorMaker instance;
    return instance;
}

class UsesFactors {
public:
    UsesFactors() {}

    void printFactor(int key) const
    {
        cout << getFactorMaker().getFactor(key) << endl;
    }
};

int main(int argc, char *argv[])
{
    const UsesFactors obj;

    for (int i = 0; i < 10; ++i)
        obj.printFactor(i);

    for (int i = 0; i < 10; ++i)
        obj.printFactor(i);

    return EXIT_SUCCESS;
}

(1) نمط المفرد يمكن تفويتها بشكل صارخ. لذا، يرجى الامتناع عن بالجنون مع ذلك إذا كنت ترى أنه لأول مرة.

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

double AdjustData(double d) const {
   static const double kAdjustFactor = LongRunningOperationToFetchFactor();
   return kAdjustFactor * d;
}

وبهذه الطريقة يمكنك جلب سوى عامل واحد.

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