Подтвердить что ты не робот

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

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

  • Вы используете ключ для поиска объекта (то же, что и в 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.

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

Ник

4b9b3361

Ответ 1

Ive собрал относительно простой 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;
    }
};

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

Ответ 2

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

Ответ 3

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

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

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