如何实现可变大小的缓存对象以减少C ++中的内存分配?

在表演之前,人们会把我的脑袋撕掉:是的,我在问这个之前做过剖析:) 我再次看到我的一个类型容器,虽然我有一个有效的解决方案,但性能很差,因为缓存的每种类型的项都会导致堆上的单独分配(这当然是昂贵的)。 基于对程序输入的静态分析,我找到了一种方法来了解可能放在我的缓存对象中的所有对象所需的总大小。基本上,我有一个可以在给定缓存对象中构造的对象列表,所以我知道我可能需要缓存的大小是什么,而不是在编译时 - 仅运行时。 基本上,我想要做的是
boost::make_shared
做什么 - 获取单个内存块,并在同一个内存块中构造
shared_ptr
位以及受控对象。 我不必担心保留复制行为,因为缓存对象是不可复制的并且由客户端通过指针传递(它通常存储在类似
ptr_vector
std::auto_ptr
的东西中)。 然而,我并不熟悉如何实现这样的容器,即如何遵循对齐限制等。 在伪代码中,我想做什么:
//I know a lot of what's in here is not portable -- I need to run only on x86
//and x64 machines. Yes, this couple of classes looks hacky, but I'd rather
//have one hacky class than a whole programfull :)

class CacheRegistrar
{
    //Blah blah
public:
    //Figures out what objects will be in the cache, etc
    const std::vector<std::size_t>& GetRequiredObjectSizes() const;
    //Other stuff...
    template <typename T>
    void RegisterCacheObject();
    template <typename T>
    std::size_t GetObjectIndex() const;
    // etc.
};

class CacheObject;

std::auto_ptr<CacheObject> CacheObjectFactory(const CacheRegistrar& registrar)
{
    //Pretend this is in a CPP file and therefore CacheObject is defined...
    const std::vector<size_t>& sizes(registrar.GetRequiredObjectSizes());
    std::size_t sumOfCache = std::accumulate(sizes.begin(), sizes.end());
    sumOfCache += sizeof(CacheObject);
    boost::scoped_array<char> buffer(new char[] sumOfCache);
    CacheObject *obj = new (reinterpret_cast<void *>(buffer.get())) CacheObject;
    buffer.release(); //PSEUDOCODE (boost::scoped_array has no release member);
    return std::auto_ptr<CacheObject>(obj); //Nothrow
}

class CacheObject
{
    CacheRegistrar *registrar; //Set by my constructor
public:
    template<typename T>
    T& Get()
    {
        char * startOfCache = reinterpret_cast<char *>(this) + 
            sizeof(CacheObject);
        char * cacheItem = startOfCache + registrar->GetObjectIndex<T>();
        return *reinterpret_cast<T*>(cacheItem);
    }
};
这是我的一般概念吗?有没有更好的方法来实现这一目标?     
已邀请:
但首先,请阅读Andrei Alexandrescu撰写的关于他认为应该在该章中所写的内容的一篇文章 - 一种使用Heap Layers构建堆的方法(真正由你的)。我使用Heap Layers构建了Hoard,DieHard和DieHarder,以及我们的OOPLSA 2002论文中使用的自定义分配器,重新考虑自定义内存分配,在开始创建自定义分配器之前,您还应该阅读它。     
查看Loki小对象分配器。 快速谷歌搜索没有产生任何直接的人性化文档。有DOxygen生成的文档,但不是特别grokkable。然而,Andrei Alexandrescu的“现代C ++设计”中记录了设计和实现。 如果您只想对给定类的对象进行有效的回收,那么请考虑一个简单的自由列表&ndash;可能是原始存储块的空闲列表。 干杯&amp;心连心,     
我看到的关键问题是返回 auto_ptr的 用于以非默认方式分配的内存。你可以通过定义一个合适的重载删除来解决这个问题,但最好将你自己的destroy函数定义为工厂的一部分。如果这样做,您还可以在Cache类中本地化内存管理,从而可以更自由地提高该类本地的性能。 如果当然,使用智能指针来控制内存管理是一个好主意;你需要做的是定义你自己的分配器并定义一个smart_ptr来使用它。 作为参考,管理自定义分配的另一种方法是定义自定义新运算符。即这种事:
struct Cache
{
    void* allocate(size_t size)
    {
        size_t blockSize = sizeof(size_t) + size;
        // Placeholder: do what ever appropriate to blocks of size 'blockSize'
        return malloc(blockSize);
    }
    void destroy(void* p)
    {
        size_t* block = reinterpret_cast<size_t*>(p);
        size_t blockSize = *block;
        // Placeholder: do what ever appropriate to blocks of size 'blockSize'
        free(p);
    }

};
Cache cache;


void* operator new (size_t size, Cache& cache )
{
    return cache.allocate(size);
}

struct CacheObject 
{
    void operator delete(void* p)
    {
        cache.destroy(p);
    }
};


CacheObject* co = new (cache) CacheObject;
    

要回复问题请先登录注册