C++ 对象的通用缓存

C++ 对象的通用缓存,c++,stl,boost,C++,Stl,Boost,有人知道对象模板缓存的任何实现吗 使用键查找对象(与std::map中相同) 指定可以同时在缓存中的最大对象数 有一些工具可以创建缓存中找不到的对象 有一些工具可以知道何时从缓存中丢弃对象 例如: typedef cache<int, MyObj*> MyCache; MyCache oCache; oCache.SetSize(1); oCache.Insert(make_pair(1, new MyObj()); oCache.Touch(1); MyObj* oldObj

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

  • 使用键查找对象(与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);

...
typedef-cache-MyCache;
MyCache-oCache;
oCache.SetSize(1);
oCache.Insert(制作一对(1,新的MyObj());
oCache.Touch(1);
MyObj*oldObj=oCache.Delete(1);
...
它可以像LRU或MRU缓存一样简单

欢迎任何建议


Nic

在一个应用程序中,我很难想象它会加速/提高存储显然可以重新创建的对象的性能(hip:因为它们可以在缓存停止时自动丢弃)。 sw缓存需要通过AssociationVISM代码获取内存,这肯定比内存分配和构造函数运行(主要是内存初始化)要慢

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


从整体上看,缓存代码在冗余的同时会减慢进程。

我将一个相对简单的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;
    }
};
模板
类LRUCache
{
大小\u t最大大小;
地图数据;
std::美国乔治亚州名单;
std::function onEject=[](std::pair x){};
void moveToFront(typename std::list::iterator itr)
{
if(itr!=usageOrder.begin())
拼接(usageOrder.begin(),usageOrder,itr);
}
void trimToSize()
{
while(data.size()>maxSize)
{
auto-itr=data.find(usageOrder.back());
一个对象(std::pair(itr->first,*(itr->second));
data.erase(usageOrder.back());
擦除(--usageOrder.end());
}
}
公众:
typedef std::pair value_type;
typedef K key_type;
typedef V映射_类型;
LRUCache(大小\u t最大条目):最大大小(最大条目)
{
数据保留(maxEntries);
}
大小\u t大小()常量
{
返回data.size();
}
无效插入(常量值\u类型和v)
{
USAGORDER.向前推(v.第一);
data.insert(typename映射::value_type(v.first,usageOrder.begin());
修剪尺寸();
}
布尔包含(常数K&K)常数
{
返回数据。计数(k)!=0;
}
V&at(常数K&K)
{
自动itr=在(k)处的数据;
移动前端(itr);
返回*itr;
}
作废setMaxEntries(大小\u t maxEntries)
{
maxSize=maxEntries;
修剪尺寸();
}
无效接触(常数K&K)
{
at(k);
}
模板
V&getOrCompute(常数K&K)
{
如果(!data.contains(k))插入(value_type(k,Compute());
返回(在(k)处);
}
void setOnEject(decltype(onEject)f)
{
onEject=f;
}
};
我认为符合您的标准。需要添加或更改的内容?

您可以使用该库。
很容易实现。

如果对象的(重新)创建比键->值查找慢得多怎么办?并不是每个构造函数都“主要是内存初始化”我明白为什么会投反对票:我没有提供答案。所以我试图得到一个答案:现在MMU会将包含非最近使用的缓存对象的内存标记为低使用率,因此候选内存将被发送到硬盘上的页面文件…假设有HDD。所以,从HDD中重新获取丢失的缓存对象,iso运行代码重新创建ob但是,只有在非常麻烦的情况下才是“正确的”@Nicolas:你的具体情况是什么?我想你混合了CPU缓存和其他类型的数据缓存。OP寻找的是数据缓存,而不是CPU。map的性能很容易变得糟糕。我建议你使用哈希表。如果可以的话,将其设为编译时固定大小。与其添加列表,不如扫描它。@BitWhistler这确实使用了哈希表-by default std::unordered_map是一个哈希表。我认为编译时固定大小根本不是一个好主意-存储大小的开销非常低,这允许根据需要更改大小。什么意思不是保留一个列表,而是扫描它?该列表跟踪插入顺序,以便可以删除LRU条目。对不起,你知道吗“是的。我想我看到了std::map。不过,预分配所有内容都有不重新分配的优势。重新分配是这里最大的成本。列表上的想法也是一样的。你应该让所有这些节点四处浮动……最好在条目中有年龄,或者在条目中有一个单独链接的列表。”。