当前位置: 首页 > wzjs >正文

老鸭窝网站正在建设中网站美工设计

老鸭窝网站正在建设中,网站美工设计,网站建设i rsky,上海公司注册网目录 申请内存 释放内存 PageCache代码框架 windows下直接向堆申请页为单位的大块内存 申请内存 1.当central cache向page cache申请内存时,page cache先检查对应位置有没有span,如果没有则向更大页寻找一个span,如果找到则分裂成两个。比…

目录

申请内存

释放内存

PageCache代码框架

windows下直接向堆申请页为单位的大块内存


申请内存

1.当central cache向page cache申请内存时,page cache先检查对应位置有没有span,如果没有则向更大页寻找一个span,如果找到则分裂成两个。比如,申请的是4页的span,4页后面没有挂span,则向后面寻找更大的span,假设在10页page位置找到一个span,则将10页page span分裂为一个4页page span和一个6页page span。

2.如果找到_spanList[128]都没有合适的span,则向系统使申请128页的page span挂在自由链表中,再重复1中的过程。

3.需要注意的是,central cache和page cache的核心结构都是spanlist的哈希桶,但是它们有本质的区别,central cache中的哈希桶,是按跟thread cache一样的大小对齐关系映射的,它的spanlist中挂的span中的内存都被按映射关系切好链接成小块内存的自由链表。而page cache中的spanlist是按下标桶号映射的,也就是说第i号桶挂的span都是i页内存。

Span* PageCache::NewSpan(size_t k)
{assert(k > 0);//大于128 page直接向堆申请if (k > NPAGES - 1){void* ptr = SystemAlloc(k);//Span* span = new Span;Span* span = _spanPool.New();span->_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;span->_n = k;//_idSpanMap[span->_pageId] = span;_idSpanMap.set(span->_pageId, span);return span;}//先检查第k个桶里面有没有spanif (!_spanlists[k].Empty()){Span* kSpan = _spanlists[k].PopFront();//建立id和span的映射,方便central cache回收小块内存时,查找对应的spanfor (size_t i = 0; i < kSpan->_n; i++){//_idSpanMap[kSpan->_pageId + i] = kSpan;_idSpanMap.set(kSpan->_pageId + i, kSpan);}return kSpan;}//检查一下后面的桶里面有没有span,如果有可以把它进行切分for (size_t i = k + 1; i < NPAGES; i++){//把当前这个桶切分成一个k页的span和一个n-k页的span//k页的span返回给central cache//n-k页span挂到第n-k桶中去if (!_spanlists[i].Empty()){Span* nSpan = _spanlists[i].PopFront();//Span* kSpan = new Span;Span* kSpan = _spanPool.New();//在nSpan的头部切一个k页下来//k页span返回//nSpan再挂到对应映射的位置kSpan->_pageId = nSpan->_pageId;kSpan->_n = k;nSpan->_pageId += k;nSpan->_n -= k;_spanlists[nSpan->_n].PushFront(nSpan);//存储nSpan的首尾页号跟nSpan映射,方便page cache回收内存//进行合并查找/*_idSpanMap[nSpan->_pageId] = nSpan;_idSpanMap[nSpan->_pageId + nSpan->_n - 1] = nSpan;*/_idSpanMap.set(nSpan->_pageId, nSpan);_idSpanMap.set(nSpan->_pageId + nSpan->_n - 1, nSpan);//建立id和span的映射,方便central cache回收小块内存时,查找对应的spanfor (size_t i = 0; i < kSpan->_n; i++){//_idSpanMap[kSpan->_pageId + i] = kSpan; _idSpanMap.set(kSpan->_pageId + i, kSpan);}return kSpan;}}//走到这个位置说明没有大页的span了//这个时候就去找堆要一个128页的span//Span* bigSpan = new Span;Span* bigSpan = _spanPool.New();void* ptr = SystemAlloc(NPAGES - 1);bigSpan->_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;bigSpan->_n = NPAGES - 1;_spanlists[bigSpan->_n].PushFront(bigSpan);return NewSpan(k);
}

central cache中用的是一把大锁,而不是桶锁,用桶锁可能导致频繁加锁解锁(在central cache中不是一次只访问某一个桶,可能这个桶里没有page,就会向更大的page桶去要),这样导致效率低。  

释放内存

如果central cache释放回一个span,则依次寻找span的前后page id(页号)的span是否空闲,如果有就合并,合并出更大的页,如果可以合并继续向前寻找。这样就可以将切小的内存合并收缩成大的span,减少内存碎片。

void PageCache::ReleaseSpanToPageCache(Span* span)
{//大于128page的直接还给堆if (span->_n > NPAGES - 1){void* ptr = (void*)(span->_pageId << PAGE_SHIFT);SystemFree(ptr);//delete span;_spanPool.Delete(span);return;}//对span前后的页,尝试进行合并,缓解内存碎片的问题while (1){PAGE_ID prev_Id = span->_pageId - 1;//auto ret = _idSpanMap.find(prev_Id);前面的页号没有,不合并了//if (ret == _idSpanMap.end())//{//	break;//}auto ret = (Span*)_idSpanMap.get(prev_Id);if (ret == nullptr){break;}//前面相邻页的span在使用,不合并了Span* prevSpan = ret;if (prevSpan->_isUse == true){break;}// 合并出超过128页的span没办法管理,不合并了if (prevSpan->_n + span->_n > NPAGES - 1){break;}span->_pageId = prevSpan->_pageId;span->_n += prevSpan->_n;_spanlists[prevSpan->_n].Erase(prevSpan);//delete prevSpan; // 这里释放的是new出来的span对象,而不是对应的内存,//内存是SystemAlloc申请出来的,应该由SystemFree释放_spanPool.Delete(prevSpan);}//向后合并while (1){PAGE_ID nextId = span->_pageId + span->_n;/*auto ret = _idSpanMap.find(nextId);if (ret == _idSpanMap.end()){break;}*/auto ret = (Span*)_idSpanMap.get(nextId);if (ret == nullptr){break;}Span* nextSpan = ret;if (nextSpan->_isUse == true){break;}if (span->_n + nextSpan->_n > NPAGES - 1){break;}span->_n += nextSpan->_n;_spanlists[nextSpan->_n].Erase(nextSpan);//delete nextSpan;_spanPool.Delete(nextSpan);}_spanlists[span->_n].PushFront(span);span->_isUse = false;/*_idSpanMap[span->_pageId] = span;_idSpanMap[span->_pageId + span->_n - 1] = span;*/_idSpanMap.set(span->_pageId, span);_idSpanMap.set(span->_pageId + span->_n - 1, span);
}

另外,我们在查找地址所对应的span时,可以通过_idSpanMap中去找。这个_idSpanMap我们会在PageCache中申请和切分大块Span时会维护。

Span* PageCache::MapObjectToSpan(void* obj) 
{PAGE_ID id = ((PAGE_ID)obj >> PAGE_SHIFT);//std::unique_lock<std::mutex> lock(_pageMtx);/*auto ret = _idSpanMap.find(id);if (ret != _idSpanMap.end()){return ret->second;}else{assert(false);return nullptr;}*/auto ret = (Span*)_idSpanMap.get(id);assert(ret != nullptr);return ret;
}

PageCache代码框架

//page cache也用单例模式
class PageCache
{
public:static PageCache* GetInstance(){return &_sInst;}//获取从对象到span的映射Span* MapObjectToSpan(void* obj);//释放空闲span回到Pagecache,并合并相邻的spanvoid ReleaseSpanToPageCache(Span* span);//获取一个K页的spanSpan* NewSpan(size_t k);std::mutex _pageMtx;private:PageCache() {}PageCache(const PageCache&) = delete;PageCache& operator=(const PageCache&) = delete;SpanList _spanlists[NPAGES];ObjectPool<Span> _spanPool; //定长内存池,用它来new出Span对象,而不是用系统接口new//std::unordered_map<PAGE_ID, Span*> _idSpanMap;TCMalloc_PageMap1<32 - PAGE_SHIFT> _idSpanMap;static PageCache _sInst;
};

windows下直接向堆申请页为单位的大块内存

// 直接去堆上按页申请空间
inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32void* ptr = VirtualAlloc(0, kpage * (1 << PAGE_SHIFT), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else// linux下brk mmap等
#endifif (ptr == nullptr)throw std::bad_alloc();return ptr;
}inline static void SystemFree(void* ptr)
{
#ifdef _WIN32VirtualFree(ptr, 0, MEM_RELEASE);
#else// sbrk unmmap等
#endif
}


文章转载自:

http://YaLDzGAf.rmqLf.cn
http://74lCXFFm.rmqLf.cn
http://n7SbeZ78.rmqLf.cn
http://SzUy0iJS.rmqLf.cn
http://QRCcQy9h.rmqLf.cn
http://zMFLhTnE.rmqLf.cn
http://QEIaOJed.rmqLf.cn
http://oli5iSd7.rmqLf.cn
http://xxV5ieWp.rmqLf.cn
http://rcRnB4P7.rmqLf.cn
http://dfaJKWFJ.rmqLf.cn
http://0VjOxqV2.rmqLf.cn
http://zkR6A7HU.rmqLf.cn
http://pkZLnh8w.rmqLf.cn
http://urHWciM3.rmqLf.cn
http://XdsHr72S.rmqLf.cn
http://oPY9KoZG.rmqLf.cn
http://VWYi8Vbx.rmqLf.cn
http://7KACyLEs.rmqLf.cn
http://AzH96urT.rmqLf.cn
http://9FafRcIK.rmqLf.cn
http://NY75mh6M.rmqLf.cn
http://RGL3EGDh.rmqLf.cn
http://w0HgeYBc.rmqLf.cn
http://21FfE4QG.rmqLf.cn
http://9pbJlQH2.rmqLf.cn
http://wJWZQMe2.rmqLf.cn
http://S5ljdA6m.rmqLf.cn
http://Gb3pTg0w.rmqLf.cn
http://GSiJ1tTw.rmqLf.cn
http://www.dtcms.com/wzjs/738155.html

相关文章:

  • 网站开发体会免费全能网站空间
  • 可以直接进入网站的正能量照片公司建设网站需要去哪报备
  • 哪些做直播卖食品的网站软文营销的技巧有哪些?
  • 高端网站制作网站设计做网站一定要psd吗
  • 楚天网站建设合同自贡市城市建设投资开发集团有限公司网站
  • 长春市快速建站网站网络电话免费版
  • 佛山外贸网站建设资讯丰台网站建设公司
  • 集团酒店网站建设制作网站能挣钱
  • 住建部工程建设标准网站电脑网站 源码
  • asp做购物网站app制作平台推荐
  • 个人网站用wordpress吗推荐一些做电子的网站
  • 网站页面如何设计图今天天津最新通告
  • 网站开发技术孵化网页一键生成小程序
  • 做网站挣钱快又多爱站工具包的模块
  • 南阳集团网站建设网站开发 网页设计北京师范大学出版社
  • 做一个网站多久子目录安装wordpress
  • 微信上建微网站要钱吗wordpress 仿头条主题
  • 广州市海珠区建设局网站网站制作流程一般制作流程?
  • 毕业设计做网站应该学什么贵阳网站建设多钱钱
  • 海南做网站的技术公司个人网站模板h5
  • 做数字艺术设计的网站企业网站首页效果图设计与制作
  • 做网站编辑要会什么陕西网站建设咨询
  • 网站托管 建设方案成都建设网站的公司有哪些
  • 比较好的h5网站新乐市建设银行网站
  • 青海省建设厅报名网站成都装修建材网站建设
  • 扁平化网站模板专业网站定制团队
  • 泸州建设厅官方网站面料做电商 哪个网站好
  • 当涂县微网站开发免费网站的资源可以发公众号吗
  • 装修的网站信息网站 cms
  • 云南专业网站建站建设姜堰区住房和城乡建设局网站