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

房产公司网站模板做服装招聘的网站有哪些内容

房产公司网站模板,做服装招聘的网站有哪些内容,seo关键词如何布局,wordpress主题博客一号💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:项目日记-高并发内存池⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你做项目   🔝🔝 开发环境: Visual Studio 2022 项目日…

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:项目日记-高并发内存池⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你做项目
  🔝🔝
开发环境: Visual Studio 2022


在这里插入图片描述

项目日记

  • 1. 前言
  • 2. 页缓存的具体结构
  • 3. 页缓存分配内存的全过程
  • 4. 页缓存分配内存的代码实现
  • 5. 优化代码,并完全脱离malloc
  • 6. 总结以及代码拓展

1. 前言

在页缓存这一层中,负责给中心缓存
分配大块儿的内存,以及合并前后空
闲的内存,这一层为整体加锁!

本章重点:

本篇文章着重讲解内存池第三层:
页缓存的基本成员变量和函数,以
页缓存的具体结构是怎样的.了解
完基础结构后,会详解讲解中心缓存
层来申请内存时的具体步骤!


2. 页缓存的具体结构

页缓存也是一个哈希桶结构,但它的映射
规则和前两层不同,它的规则是:

K号桶中的大块儿内存就是K页

并且它总共是有128号桶,申请小于
128页的内存都会在内存池中申请

在这里插入图片描述

//单例模式
class PageCache
{
public:static PageCache* GetInstance(){return &_singleton;}//获取一个K页的spanSpanData* NewSpan(size_t k);std::mutex _mtx;//pagecache不能用桶锁,只能用全局锁,因为后面可能会有大页被切割为小页// 获取从对象到span的映射,给我一个地址,返回这个地址对应的spanSpanData* MapObjectToSpan(void* obj);// 释放空闲span回到Pagecache,并合并相邻的spanvoid ReleaseSpanToPageCache(SpanData* span);
private:PageCache(){}PageCache(const PageCache& obj) = delete;
private:std::unordered_map<PAGE_ID, SpanData*> _idSpanMap;//存储页号和桶中对应的span的映射,解决换回来的内存对应哪个span的问题SpanList _spanList[N_PAGES];static PageCache _singleton;
};

3. 页缓存分配内存的全过程

当中心缓存中没有内存时,会去页缓存
申请一个span结构,要经过下面几步:

  1. 根据中心缓存的桶号来确定申请的span是几页的
  2. 根据中心缓存想要申请的页数,找到页缓存中对应的桶(k页对应k号桶)
  3. 情况一: 页缓存的K号桶中存在span结构,直接将这块儿内存返回给中心缓存
  4. 情况二: 页缓存的K号桶没有span结构,但是K+1到128号桶中存在span结构,假设n号桶有span,则将这个大页的span切分为一个k页的span和一个n-k页的span,k页的span返回给中心缓存去使用,而将n-k页的span重新挂在n-k号桶中
  5. 情况三: k到128号桶都没有span,此时页缓存会向系统申请一份128页大小的内存,并挂在128号桶中,再将这个128页的span切分为k页的span和128-k页的span,也就转换为了情况二!

在这里插入图片描述

并且在这个过程中,页缓存将一个span
分配给中心缓存后,会记录下来这块儿
内存的页号和span的映射关系,方便后续
回收内存的时候再使用!


4. 页缓存分配内存的代码实现

在pagecache.h文件中:

SpanData* PageCache::NewSpan(size_t k)//去第K个桶中找span给central,此i号桶中挂的span都是i页内存
{//若K桶中有,直接返回,K桶没有span就往后找去分裂大spanassert(k > 0);if (k > N_PAGES - 1)//如果申请的页数大于了128页,pagecache只能向堆申请了{void* ptr = SystemAlloc(k);SpanData* span = new SpanData();span->_pageid = (PAGE_ID)ptr >> PAGE_SHIFT;span->_n = k;_idSpanMap[span->_pageid] = span;return span;}//先检查K号桶有无span,有直接返回一个if (!_spanList[k].Empty()){SpanData* KSpan = _spanList[k].PopFront();for (PAGE_ID i = 0; i < KSpan->_n; i++)_idSpanMap[KSpan->_pageid + i] = KSpan;return KSpan;}//走到这儿代表k号桶为空,检查后面的桶有没有span,拿出来分裂成两个小spanfor (int i = k + 1; i < N_PAGES; i++){if (!_spanList[i].Empty())//k页的span返回给centralcache,i-k页的span挂到i-k号桶中{SpanData* ISpan = _spanList[i].PopFront();SpanData* KSpan = new SpanData;KSpan->_pageid = ISpan->_pageid;KSpan->_n = k;ISpan->_pageid += k;//把头K页切分给KSpanISpan->_n -= k; //页数从i变为i-k_spanList[ISpan->_n].PushFront(ISpan);//再将后i-k页分配给i-k号桶//存储Ispan的首尾页号跟ISpan的映射关系// 这里只需要映射首尾页而不需要像下面一样全部页都映射,因为下面切分出去的span会被切分为小块儿内存// 这些小块儿内存都有可能被使用,所以当它们还回来时这些小块儿内存可能映射的是不同的页,但这些页都属于这个KSpan// 然而ISpan中不会被切分为小块儿内存,它只需要关心是否和它的前后页合并,所以这里只需要映射首尾页号与ISpan的关系// ISpan作为要合并页的前面,如1000页要合并ISpan是1001页,那么1001到1001+n都是空闲的!ISpan作为要合并页的后面,如100页要合并ISpan是999页,那么999-n都是空闲的!//_idSpanMap[ISpan->_pageid] = ISpan;//_idSpanMap[ISpan->_pageid + ISpan->_n - 1] = ISpan;_idSpanMap.set(ISpan->_pageid, ISpan);_idSpanMap.set(ISpan->_pageid + ISpan->_n - 1, ISpan);//建立id和span的映射关系,方便centralcache回收小块内存时查看哪块内存在哪块spanfor (PAGE_ID i = 0; i < KSpan->_n; i++)//返回的KSpan中一共有n页,并且每一页的页号都对应KSpan这个地址_idSpanMap[KSpan->_pageid + i] = KSpan;return KSpan;}}//走到这里说明后面所有的桶都没有span了//这时需要向堆申请一个128页的span再拿来做切分SpanData* bigSpan = _spanPool.New();void* ptr = SystemAlloc(N_PAGES - 1);bigSpan->_pageid = (PAGE_ID)ptr >> PAGE_SHIFT;bigSpan->_n = N_PAGES - 1;_spanList[bigSpan->_n].PushFront(bigSpan);//将这个128页的span插入到桶中return NewSpan(k);//再次调用自己,这次一定会在前面的for循环处返回
}

这个地方有一个设计的比较巧妙的点,
那就是出现情况三的时候,向系统申请了
128页的空间后,再次调用这个函数就一定
会出现情况二,从而在for循环中走完整个过程


5. 优化代码,并完全脱离malloc

细心的同学会发现,在这个函数中使用到了new操作符,然而了解new底层原理的同学应该知道,new的底层实际上是用的malloc来申请的空间,但是我们这个项目就是为了完全脱离malloc函数来实现一个多线程下高效的内存池,所以这里一定不能使用new!

使用之前编写的定长池来舍弃new!

如果你不知道或忘记了定长池是什么
请看这篇文章: 定长池的实现

首先, 在页缓存类中添加上一个成员变量: 定长池类, 然后在使用new的地方,把new全部替换为用定长池申请空间!

在这里插入图片描述
在这里插入图片描述


6. 总结以及代码拓展

页缓存分配内存的一环设计的是
非常的巧妙,但是页缓存真正巧妙
的地方是在合并空闲内存的一环!

对代码的拓展:
我们会发现页缓存结构中调用了
好几次向系统申请内存的函数,
这个地方只做了解,会用接口就行

inline static void* SystemAlloc(size_t kpage)//申请kpage页内存
{
#ifdef _WIN32void* ptr = VirtualAlloc(0, kpage << PAGE_SHIFT, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else// linux下brk mmap等直接向系统申请内存的方式
#endifif (ptr == nullptr)throw std::bad_alloc();return ptr;
}

🔎 下期预告:页缓存的具体实现(下)🔍
http://www.15wanjia.com/news/174023.html

相关文章:

  • php网站屏蔽词怎么做中山英文网站建设
  • 网站被挂黑链怎么办天津百度推广电话号码
  • 东莞网站制作企业网站设计官网入口
  • 域名注册了如何做网站网站开发的后端
  • 做网站水印大连零基础网站建设培训班
  • 免费网站建设免代码广告免费发布信息平台
  • php网站安装图解能进入各种网站的浏览器
  • 门户网站改造方案互联网项目推广
  • 新网站推广方法宁波关键词排名优化平台
  • 网站建设公司推荐时代创信怎么自己创建小程序
  • 网站建设前的市场分析做一个简单网站
  • 企业网站的特点建立网站的方式
  • 快速搭建网站 优帮云网站开发 公司 深圳
  • 佳木斯建设工程交易中心网站做标签网站邀请码
  • 杭州低价做网站手机网站搭建教程
  • 微网站php源码重庆做网站推广公司
  • 重庆秀山网站建设报价django 开发一个公司网站
  • 怎么样学做网站旅游网站论文
  • 小程序有做门户网站关键词搜索查找工具
  • 建立网站的关键是定位网站建设策划案模板
  • 沈阳网站建设tlmh锡林郭勒盟建设局网站
  • 如何破解网站后台账号和密码分类网站有哪些
  • 已有网站开发安卓app虚拟主机推荐
  • 公司的论坛与网站绑定网络营销平台都有哪些
  • 曹妃甸网站建设潍坊网站制作 熊掌号
  • 外贸网站架构xampp配置多网站
  • 老板让我做网站负责人好学校平台网站模板下载
  • 马云为什么做网站html表单的完整代码
  • 企业网站建设很有必要网站数据库维护都是做什么
  • 个人做的好的淘宝客网站2019网页游戏排行榜