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


12

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

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

Например:

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

-6

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

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

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

  0

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

  0

Я понимаю, почему downvote: я не отвечаю. Итак, я пытаюсь его получить: Теперь MMU будет отмечать память, содержащую неработающие кешированные объекты, как низкоуровневые, поэтому кандидат должен быть отправлен в файл-страницу на жестком диске ... при условии, что есть HDD. Таким образом, повторное извлечение отсутствующего кэшированного объекта с жесткого диска, iso running code для воссоздания объекта, будет только в очень громоздком множестве обстоятельств «правильным». @Nicolas: Каковы ваши конкретные обстоятельства? 22 июн. 102010-06-22 19:55:59

+1

Я думаю, что вы смешиваете кеш процессора и кеширование другого типа. OP искал кеш данных, а не CPU. 27 фев. 132013-02-27 10:41:49


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; 
    } 
}; 

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

  0

Производительность карты может стать ужасной. Я предлагаю вам использовать хеш-таблицу. Сделайте это, скопируйте фиксированный размер времени, если сможете. Вместо добавления списка сканируйте его. 11 фев. 162016-02-11 23:47:07

  0

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

  0

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


1

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