【问题标题】:Generic cache of objects对象的通用缓存
【发布时间】:2010-09-12 11:34:29
【问题描述】:

有人知道对象模板缓存的任何实现吗?

  • 您使用键来查找对象(与 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 缓存一样简单。

欢迎提出任何建议!

网卡

【问题讨论】:

    标签: c++ stl boost


    【解决方案1】:

    您可以使用Boost.MultiIndex 库。 很容易实现MRU cache

    【讨论】:

      【解决方案2】:

      我已经把一个相对简单的 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 这确实使用哈希表 - 默认情况下 std::unordered_map 是一个哈希表。我认为编译时固定大小根本不是一个好主意-存储大小的开销非常低,这允许根据需要更改大小。你是什​​么意思,而不是保留一个列表,扫描它?该列表跟踪插入的顺序,以便可以删除 LRU 条目。
      • 对不起,你是对的。我以为我看到了std::map。尽管如此,预先分配所有内容将具有不重新分配的优势。重新分配是这里最大的成本。清单上的想法相同。你会让所有这些节点四处浮动......最好在条目中包含年龄或在条目中插入一个单链表。
      【解决方案3】:

      在一个应用程序中,我几乎无法想象它会加速/提高性能来存储显然可以重新创建的对象(臀部:因为当缓存达到顶峰时它们可以被自动丢弃)。 sw 缓存需要通过关联代码获取内存,这肯定比内存分配和构造函数运行(主要是内存初始化)要慢。

      除了手动用户配置以避免分页机制(恰好是为了提高性能,顺便说一句),大多数操作系统为您在磁盘上“缓存”内存......它是“分页”,一种“高成本缓存”的形式",因为没有东西被扔掉,它是由特定的硬件完成的,一个称为内存管理单元的子处理单元......

      总体而言,缓存代码会减慢进程,同时又是冗余的。

      【讨论】:

      • 如果对象的(重新)创建比键->值查找慢得多怎么办?并非每个构造函数都是“主要是内存初始化”。
      • 我明白为什么投反对票:我没有提供答案。所以我试图得到一个:现在MMU会将包含非最近使用的缓存对象的内存标记为低使用率,因此候选被发送到硬盘上的页面文件......假设有一个HDD。因此,从 HDD 重新获取丢失的缓存对象,iso 运行代码来重新创建对象,只有在非常麻烦的情况下才是“正确的”。 @Nicolas:你的具体情况是什么?
      • 我认为您将 CPU 缓存和其他类型的数据缓存混合使用。 OP 寻找的是数据缓存,而不是 CPU。
      猜你喜欢
      • 1970-01-01
      • 2018-05-25
      • 2010-10-09
      • 1970-01-01
      • 2016-03-29
      • 2012-06-06
      • 2012-10-14
      • 2018-05-27
      • 1970-01-01
      相关资源
      最近更新 更多