Общий кеш объектов - PullRequest
       18

Общий кеш объектов

12 голосов
/ 23 сентября 2008

Кто-нибудь знает какую-либо реализацию шаблонного кэша объектов?

  • Вы используете ключ для поиска объекта (так же, как в std :: map <>)
  • Вы указываете максимальное количество объектов, которые могут одновременно находиться в кэше
  • Есть средства для создания объекта, не найденного в кеше
  • Есть средства, позволяющие узнать, когда объект сбрасывается из кэша

Например:

typedef cache<int, MyObj*> MyCache;
MyCache oCache;
oCache.SetSize(1);
oCache.Insert(make_pair(1, new MyObj());
oCache.Touch(1);
MyObj* oldObj = oCache.Delete(1);

...

Это может быть простой кэш LRU или MRU.

Любые предложения приветствуются!

Nic

Ответы [ 3 ]

2 голосов
/ 07 апреля 2016

Вы можете использовать библиотеку Boost.MultiIndex . Легко реализовать MRU кеш .

1 голос
/ 03 февраля 2016

Я собрал относительно простой кэш LRU, построенный из карты и связанного списка:

template<typename K, typename V, typename Map = std::unordered_map<K, typename std::list<K>::iterator>>
class LRUCache
{
    size_t maxSize;
    Map data;
    std::list<K> usageOrder;
    std::function<void(std::pair<K, V>)> onEject = [](std::pair<K, V> x){};

    void moveToFront(typename std::list<K>::iterator itr)
    {
        if(itr != usageOrder.begin())
            usageOrder.splice(usageOrder.begin(), usageOrder, itr);
    }


    void trimToSize()
    {
        while(data.size() > maxSize)
        {
            auto itr = data.find(usageOrder.back());

            onEject(std::pair<K, V>(itr->first, *(itr->second)));
            data.erase(usageOrder.back());
            usageOrder.erase(--usageOrder.end());
        }
    }

public:
    typedef std::pair<const K, V> value_type;
    typedef K key_type;
    typedef V mapped_type;


    LRUCache(size_t maxEntries) : maxSize(maxEntries)
    {
        data.reserve(maxEntries);
    }

    size_t size() const
    {
        return data.size();
    }

    void insert(const value_type& v)
    {
        usageOrder.push_front(v.first);
        data.insert(typename Map::value_type(v.first, usageOrder.begin()));

        trimToSize();
    }

    bool contains(const K& k) const
    {
        return data.count(k) != 0;
    }

    V& at(const K& k)
    {
        auto itr = data.at(k);
        moveToFront(itr);
        return *itr;
    }


    void setMaxEntries(size_t maxEntries)
    {
        maxSize = maxEntries;
        trimToSize();
    }

    void touch(const K& k)
    {
        at(k);
    }

    template<typename Compute>
    V& getOrCompute(const K& k)
    {
        if(!data.contains(k)) insert(value_type(k, Compute()));
        return(at(k));
    }

    void setOnEject(decltype(onEject) f)
    {
        onEject = f;
    }
};

Который, я считаю, соответствует вашим критериям. Что-нибудь нужно добавить или изменить?

0 голосов
/ 24 сентября 2008

В приложении я не могу себе представить, что это ускорит / повысит производительность для хранения объектов, которые, по-видимому, могут быть воссозданы (бедро: поскольку их можно автоматически отбрасывать, когда кэш завершается). Кэш SW потребует извлечения памяти через код ассоциативности, что, безусловно, медленнее, чем выделение памяти и выполнение конструктора (в основном инициализация памяти).

За исключением ручной настройки пользователя, чтобы избежать механизма подкачки (именно для повышения производительности, кстати), большинство ОС «кеширует» для вас память на диске ... это «подкачка», форма «дорогостоящего кеширования» ", потому что ничего не выбрасывается, и это делается специальным HW, блоком обработки, называемым Memory Management Unit ...

Кэширующий код, по большому счету, будет замедлять процессы, будучи избыточным.

...