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

百度收录较好的网站站长工具seo综合查询 分析

百度收录较好的网站,站长工具seo综合查询 分析,如何设计产品网站建设,网站 设计 深圳目录 一、Span和Spanlist 二、CentralCache 一、Span和Spanlist CentralCache其实也是哈希桶结构,只不过他是一个个的Span(Span是管理一定数量的页的结构),而且Span会管理一个freelist,用来挂起一个个的小内存块给Th…

目录

一、Span和Spanlist

二、CentralCache


一、Span和Spanlist

        CentralCache其实也是哈希桶结构,只不过他是一个个的Span(Span是管理一定数量的页的结构),而且Span会管理一个freelist,用来挂起一个个的小内存块给ThreadCache使用

        同一个SpanList桶中的Span结构必须相同,除了freelist可以有不同的挂载情况

SpanList的结构

        这其中有一个字段叫做ustCount,他记录的就是该Span中的小内存块的使用情况,每给一个到ThreadCache,该字段就++,当ThreadCache调用ListTooLong归还内存块到CentralCache的时候再--。

        一旦useCount被减到0了,则把该Span返还给PageCache。从而缓解内存碎片的问题。

当然CentralCache刚刚获取到Span的时候,useCount一定是0,那么万一此时刚好处于归还逻辑呢?岂不是又还回去了,白申请了。其实在Span中还有一个isuse表示是否正在被使用,就解决了这个问题。

//Span管理以页为单位的大块内存
struct Span
{PAGE_ID _pageId = 0;	//起始页的页号size_t _pageN=0;		//页的数量size_t _useCount=0;		//Span中有多少个小内存块被分配给ThreadCache了void* _freelist=nullptr;			//切好的小块内存块的自由链表,方便下一次分配给ThreadCache,不用在分配的时候切了,就好像定长池的memorybool _isuse=false;		//是否正在使用size_t _objSize = 0;	//小内存块的大小,即freelist中挂的一个个小对象节点的大小Span* _prev = nullptr;Span* _next = nullptr;
};//带头双向循环链表
class SpanList
{
public:SpanList(){_head = new Span();_head->_next = _head;_head->_prev = _head;}bool Empty(){return _head->_next == _head;}Span* PopFront(){Span* front = _head->_next;Erase(front);return front;}void PushFront(Span* span){Insert(Begin(),span);}Span* Begin(){return _head->_next;}Span* End(){return _head;}void Insert(Span* pos,Span* newSpan){assert(pos);assert(newSpan);//前SpanSpan* prev = pos->_prev;prev->_next = newSpan;newSpan->_prev = prev;newSpan->_next = pos;pos->_prev = newSpan;}void Erase(Span* pos){assert(pos);assert(pos!=_head);//前后SpanSpan* next = pos->_next;Span* prev = pos->_prev;prev->_next = next;next->_prev = prev;}std::mutex& GetMutex(){return _mutex;}private:Span* _head=nullptr;std::mutex _mutex;		//桶锁
};

二、CentralCache

#pragma once
#include"Common.hpp"
#include"PageCache.hpp"//单例模式---饿汉
class CentralCache
{
public:static CentralCache* GetInstance(){return &_sInstance;}// 从中心缓存获取一定数量的对象给thread cachesize_t FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size);// 获取一个非空的spanSpan* GetOneSpan(SpanList& list, size_t byte_size);// 将一定数量的对象释放到span跨度void ReleaseListToSpans(void* start, size_t byte_size);private:static CentralCache _sInstance;CentralCache() {}CentralCache(const CentralCache&) = delete;
private:SpanList _spanlists[NFREELISTS];};//inline防止多个源文件包含导致重复定义
inline CentralCache  CentralCache::_sInstance;void CentralCache::ReleaseListToSpans(void* start, size_t byte_size)
{//通过index可以知道该内存块是属于哪一个SpanList的size_t index = SizeClass::Index(byte_size);_spanlists[index].GetMutex().lock();while (start!=nullptr){void* next = NextObj(start);//1.找到该内存块是属于哪一个Span//当然可以通过内存块的地址,计算出页号,然后和SpanList中的Span的页号一个个比较,但是时间复杂度较高,采取哈希表映射Span* span = PageCache::GetInstance()->MapObjectToSpan(start);//2.把该内存块头插到Span的freelist中NextObj(start) = span->_freelist;span->_freelist = start;span->_useCount--;if (span->_useCount==0){//该Span已经没有人用了,归还到PageCache中_spanlists[index].Erase(span);span->_freelist = nullptr;span->_next = span->_prev = nullptr;_spanlists[index].GetMutex().unlock();PageCache::GetInstance()->GetMutex().lock();PageCache::GetInstance()->ReleaseSpanToPageCache(span);PageCache::GetInstance()->GetMutex().unlock();_spanlists[index].GetMutex().lock();}//一个内存块还回去了,往后走一步start = next;}_spanlists[index].GetMutex().unlock();
}Span* CentralCache::GetOneSpan(SpanList& list, size_t byte_size)
{//1.CentralCache有非空Span,直接取Span* it = list.Begin();while (it!=list.End()){if (it->_freelist!=nullptr){return it;}else{it = it->_next;}}//把CentralCache的桶锁解开,其他线程释放内存的时候,就不会阻塞了list.GetMutex().unlock();//2.如果CentralCache中没有,找PageCache要PageCache::GetInstance()->GetMutex().lock();Span* span=PageCache::GetInstance()->NewSpan(SizeClass::NumMovePage(byte_size));span->_objSize = byte_size;span->_isuse = true;PageCache::GetInstance()->GetMutex().unlock();//3.把从PageCache中要到的Span,切分成小的内存块,挂到Span的freelist中char* start = (char*)((span->_pageId) << PAGE_SHIFT);		//起始地址(为什么pageId就是系统中的页号呢?为什么系统调用堆是从0页开始呢?)size_t bytes = (span->_pageN) << PAGE_SHIFT;			//总字节数char* end = start + bytes;//先头插一个span->_freelist = start;start += byte_size;void* tail = span->_freelist;//再把剩下的插入while (start<end){//尾插NextObj(tail) = start;tail = NextObj(tail);start += byte_size;}NextObj(tail) = nullptr;//插入到SpanList的时候,需要加锁,因为插入的动作是临界资源list.GetMutex().lock();list.PushFront(span);return span;
}size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size)
{size_t index = SizeClass::Index(size);//加锁_spanlists[index].GetMutex().lock();//1.获取从非空的Span,从这个Span中获取自由链表中的内存块节点Span* span = GetOneSpan(_spanlists[index],size);assert(span);assert(span->_freelist);start = span->_freelist;end = start;size_t i = 0;size_t actualNum = 1;while(i<batchNum-1 && NextObj(end)!=nullptr){end = NextObj(end);i++;actualNum++;}span->_freelist = NextObj(end);NextObj(end)=nullptr;//2.修改Span中的使用情况span->_useCount += actualNum;//解锁_spanlists[index].GetMutex().unlock();return actualNum;
}

        值得注意的是:获取到span后我们要通过这个span的页数来知道这个span有多少内存,并且要通过这个span在程序地址空间的页号来判断这份内存的起始地址是多少!第0页的地址是0000 0000,第一页的地址是8KB,以此类推。

        为什么从PageCache拿出Span给CentralCache的时候,需要建立一个页号和Span的映射关系呢?

        因为PageCache的桶结构仍然是SpanList,但是和CentralCache不同的是:PageCache的桶中的Span是可以被修改的,即可以被切分成小的Span;而CentralCache的Span你开始的时候拿到的是多大的页,就永远是那么大了。

        ThreadCache的内存块不被使用后,归还的时候可以计算出页号(页号通过小内存块的ptr指针计算)到了CentralCache,发现这个Span在不被使用后,归还给PageCache。而PageCache又会检查我的前后Span有没有归还,如果归还了,则可以把这两个Span合并成一个大的Span,从PageCache的若干个小桶移动到一个大桶中,从而缓解外碎片的问题。

http://www.dtcms.com/wzjs/369813.html

相关文章:

  • 做充币提现的网站seo哪家好
  • 软件工程师证书报考条件长沙靠谱关键词优化公司电话
  • 国美网站建设特点现在推广一般都用什么软件
  • 网站免费建站k视频广告
  • ipad可以做网站推广吗semester怎么读
  • 网站做接口到app价格谷歌搜索引擎下载
  • php做网站目录结构跨境电商关键词工具
  • 亚马逊网站特点今日军事新闻最新消息
  • 网站布局分类seo外链在线工具
  • 网站公安备案流程直播:英格兰vs法国
  • 优秀品牌策划公司北京seo执行
  • 营销系统架构seo网络营销推广公司深圳
  • wordpress自定义注册页面企业网站seo点击软件
  • 吸引企业做网站的文章内容陕西seo优化
  • 南山网站开发重庆网站建设公司
  • 纯静态网站怎样线下营销推广方式都有哪些
  • 清远网站制作电子商务网站建设规划方案
  • 深圳自己的网站建设seo应用领域有哪些
  • 网站建设实训个人总结30002023年8月新冠
  • 自己做网站花费公众号seo排名软件
  • 做网站费用需要分摊吗网络推广的优化服务
  • 临沂网站建设技术支持seo高级教程
  • 柬埔寨做网站赌博在那边违反吗职业教育培训机构排名前十
  • 广东省网站备案查询人力资源管理师
  • 做wish选品网站 数据网站百度推广登录平台怎么收费
  • 深圳做分销网站设计网站seo综合诊断
  • 青岛建站公司推荐网站生成app工具
  • 广东建设继续教育网站首页网络营销的特点有几个
  • 德州网站制作公司牛推网
  • 新疆生产建设兵团国土局官方网站百度竞价推广登录