游戏后台Cache技术和运用

//
/*
1.为什么需要cache,有那些好处?
从下面几点考虑
后台程序会创建大量的对象,也就是动态分配内存,通常的做法是new XXX。然后在
不用的时候在delete XXX。这样new和delete会消耗一定cpu,最重要的是在长期new/delete
后会有内存碎片,而且忘记delete XXX,那就会有致命的内存泄漏这种bug将是难以调试和查找的。


内存使用策略优先级从下到下
  尽量避免动态内存分配,做到一次性内存分配,运行期间不使用new/delete)
  尽量少用动态分配内存
  优化调锁的内存池  
  使用内存分配池
  实时动态分配内存,直接使用new/delete


2.那些数据需要cache,如何评估需要的内存空间
  评估需要的内存空间,就得先确定那些是要cache的,一般像Role,Monster,Item都可以Cache,在就是确定数量
  比如一个LogicServer最大服务人数为5000,那么Role的内存所需内存大小为sizeof(Role)*5000,其他都可以这么来估算


3.确定cache策略如果保证高效找出(cache命中要高),如果实现cache和复用Cache组件
  实现方法有很多,下面是一种实现,不过可以有几个地方可以改进
  1.是否可以让cache的空间来自共享内存?
  2.是否可以不用std的容器自己实现vector和hash来支持cache内部结构?
  3.如果使用共享内存,那么在服务重启的时候如何重用上次的共享内存?
*/
template<class T>
struct MemoryBlock
{
   int key; 
   int next; 
   T data;
};


template<class T,int size>
class MemoryCache
{
private:
    void InitMemory()
    {
        for (int i=0;i<size;++i)
        {
            MemoryBlock<T>* pblock = NULL;
            pblock = &(m_Memblocks.at(i));
            pblock->key = 0;
            pblock->next = i + 1;


        }


    }


    MemoryBlock<T>* GetBlock(int index)
    {
        if (index < 0 || index >= size)
        {
            return NULL;
        }
        MemoryBlock<T>* pblock = NULL;
        pblock = &(m_Memblocks.at(index));
        return pblock;
    }


public:
    MemoryCache()
    {
       //分配空间
       m_Memblocks.resize(size);
       m_Count = 0;
       m_FreeHead = 0;
       m_Size = size;
       InitMemory();
    }
    
    T* GetDataByKey(int key)
    {
       if (0 == key)
       {
           return NULL;
       }
       std::map<int,int>::iterator iter = m_HashKey.find(key);
       if (iter == m_HashKey.end())
       {
            return NULL;           
       }
       
       int index = iter->second;
       MemoryBlock<T>* pblock = GetBlock(index);
       return &(pblock->data);
    }


    T* AllcoMemory(int key)
    {
       if (0 == key)
       {
           return NULL;
       }
       T* pdata = GetDataByKey(key); 
       if (pdata)
       {
           return pdata; //hit cache
       }
       //not find alloc memory
       int curindex = m_FreeHead;
       MemoryBlock<T>* pBlock = GetBlock(curindex);
       if (NULL == pBlock)
       {
           return NULL;
       }
       
       pBlock->key = key;
       m_FreeHead = pBlock->next;
       pBlock->next = 0;
       m_HashKey.insert(std::make_pair(key,curindex));
       return &(pBlock->data);
    }


    bool Remove(int key)
    {
        std::map<int,int>::iterator iter = m_HashKey.find(key);
        if (iter == m_HashKey.end())
        {   
            //not find
            return false;           
        }


        int index = iter->second;
        MemoryBlock<T>* pblock = GetBlock(index);
        if (pblock->key == key)
        {
            int PreIndex = index;
            pblock->next = m_FreeHead;
            pblock->key = 0;
            m_FreeHead = PreIndex;
            m_HashKey.erase(iter);
        }
      
        return true; 
    }


    int Size() { return m_Count; }
    int Capacity() { return m_Size;}
private:
    //存储实际数据
    std::vector<MemoryBlock<T> > m_Memblocks;
    //存储<key,index>
    std::map<int,int> m_HashKey;
    //当前实际元素size
    unsigned int m_Count;
    int m_Size; 
    //总是指向预分配的index
    unsigned int m_FreeHead;
};
//
struct Role
{
  int key;
  int x;
  int y;
  int hp;
};
typedef MemoryCache<Role,6000> RoleCache;
//typedef MemoryCache<Monster,10000> MonsterCache; 
int main(int argc, char** argv)
{   
    //定义一个Role cache
    RoleCache rolecacle;
    //申请空间
    Role* pRole1 = rolecacle.AllcoMemory(1000);
    //初始化Role
    pRole1->key = 1000;
    pRole1->x = 10;
    pRole1->y = 10;
    pRole1->hp = 500;


    Role* pRole2 = rolecacle.AllcoMemory(1005);
    pRole2->key = 1005;
    pRole2->x = 50;
    pRole2->y = 50;
    pRole2->hp = 200;
    //销毁对象

    rolecacle.Remove(pRole1->key);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值