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

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

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

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

Ник

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
8 109
3

Ответы 3

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

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

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

Что, если (повторное) создание объекта происходит намного медленнее, чем поиск ключ-> значение? Не каждый конструктор «в основном инициализирует память».

moswald 24.09.2008 02:10

Я понимаю, почему голос против: я не отвечаю. Итак, я пытаюсь получить один: в настоящее время MMU будет помечать память, содержащую не недавно использованные кэшированные объекты, как малоиспользуемые, следовательно, кандидат для отправки в файл подкачки на жестком диске ... при условии, что есть жесткий диск. Таким образом, повторная выборка отсутствующего кэшированного объекта с жесткого диска, исполняемый код iso для воссоздания объекта, будет «правильным» только в очень обременительном наборе обстоятельств. @Nicolas: каковы ваши конкретные обстоятельства?

jpinto3912 22.06.2010 23:55

Я думаю, вы смешиваете кеш процессора и другой тип кеша данных. OP искал кеш данных, а не CPU.

Dolanor 27.02.2013 14:41

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

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

Производительность карты может легко ухудшиться. Я бы посоветовал вам использовать хеш-таблицу. Сделайте фиксированный размер времени компиляции, если можете. Вместо того, чтобы добавлять список, просканируйте его.

BitWhistler 12.02.2016 02:47

@BitWhistler Это действительно использует хеш-таблицу - по умолчанию std :: unordered_map, которая является хеш-таблицей. Я не думаю, что фиксированный размер во время компиляции - это вообще хорошая идея - очень низкие накладные расходы на сохранение размера, и это позволяет изменять размер по мере необходимости. Что вы имеете в виду, говоря, что вместо того, чтобы вести список, отсканируйте его? Список отслеживает порядок вставки, так что запись LRU может быть удалена.

Straw1239 12.02.2016 23:57

извините, вы правы. Я думал, что видел std :: map. Тем не менее, предварительное распределение всего имеет то преимущество, что не перераспределяется. Перераспределение - самая большая стоимость здесь. Та же идея в списке. У вас были бы все эти узлы, плавающие вокруг ... лучше иметь возраст в записях или иметь односвязный список, навязчивый в записях.

BitWhistler 16.02.2016 14:07

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

Другие вопросы по теме