山东网站建设设计小清新个人网站

news/2025/9/27 16:53:40/文章来源:
山东网站建设设计,小清新个人网站,如何撰写网站建设方案,网络推广公司招聘七、高并发内存池–Page Cache 7.1 PageCache的工作原理 PageCache是以span的大小(以页为单位)和下标一一对应为映射关系的哈希桶#xff0c;下标是几就说明这个哈希桶下挂的span的大小就是几页的#xff0c;是绝对映射的关系。因为PageCache也是全局只有唯一一个的#x…七、高并发内存池–Page Cache 7.1 PageCache的工作原理 PageCache是以span的大小(以页为单位)和下标一一对应为映射关系的哈希桶下标是几就说明这个哈希桶下挂的span的大小就是几页的是绝对映射的关系。因为PageCache也是全局只有唯一一个的所以为了防止出现线程安全的问题在访问PageCache之前要先加上一把大锁锁住整个PageCache为什么这里是加一把大锁锁住整个PageCache而不是加桶锁锁住要访问的那个桶呢 因为当Central Cache向PageCache获取一个K页的span的时候在PageCache中下标为K的哈希桶中不一定有span此时PageCache并不是直接向系统堆中申请一块K页的span内存因为如果这样处理的话会出现频繁地向系统申请内存的情况并且每次向堆申请的内存都只是K页大小的如果每一次的K都是1或者2这样会使堆申请出来的内存都是很碎片化的不便于堆做内存管理所以PageCache的处理策略是如果当前下标的哈希桶中没有span对象那么就从当前位置开始往后遍历如果后面的哈希桶中有span对象就把这个span切成一个K页的kspan和一个(n-k)页的span把kspan切成一个一个的小对象连接到kspan中的自由链表并把这个切好的kspan返回给CentralCache对应位置的哈希桶剩下的(n-k)页大小的span就挂到PageCache中n-k位置的哈希桶。 如果把PageCache中剩下的所有的哈希桶都遍历完都没有找到一个span那么就向系统申请一个128(这个128是自定义的)页大小的大span重复上面的切分操作最后返回一个切好的K页的span给CentralCache对应位置的哈希桶中再让CentralCache分若干个小对象给ThreadCacheThreadCache再返回一个给上层。 综上也就不难发现PageCache不能用桶锁而是要用一把大锁因为在CentralCache向PageCache中获取一个span时不仅仅是会访问PageCache中的某一个位置的哈希桶而是有可能往后遍历其它的哈希桶并访问所以加桶锁只是锁住了一个桶并不能锁住后续遍历的其它位置的哈希桶所以这里要加一把大锁。其实从技术上来说用桶锁也是可以的只不过在遍历PageCache后面的每一个哈希桶前都要对先对这个桶加上桶锁访问完之后还要解掉桶锁如此一来必然会出现大量的上锁解锁的操作反而会降低了内存池的效率所以加一把大锁就行了。 7.2 PageCache.h //页缓存CentralCache需要向PageCache申请K页大小的spanPageCache向系统申请128页大小的span //因为PageCache也是全局只有唯一一个的所以也把PageCache设计成单例模式 class PageCache { public:static PageCache* GetInstance(){return _sInst;}//提供给CentralCache向PageCache获取一个k页的span时使用Span* NewSpan(size_t k);//根据obj的地址转换成页号进而通过哈希表找到页号对应的SpanSpan* MapObjectToSpan(void* obj);//CentralCache把span还回来给PageCachevoid ReleaseSpanToPageCache(Span* span);//PageCache是整个进程唯一的所以所有的线程都有可能//访问PageCache存在线程安全问题所以需要加锁这里是加一把大锁而不是桶锁std::mutex _pageMtx;private://单例模式需要把构造函数私有化防止别人创建对象PageCache(){}PageCache(const PageCache) delete;private:SpanList _spanLists[NPAGES];//有多少也大小的span数组就有多大下标和span的大小一一对应//声明静态对象static PageCache _sInst;//如果PageCache中所有的哈希桶都没有span需要从系统堆中申请内存时//要脱离malloc所以直接用我们写好的定长内存池申请内存即可定长内存//池中封装了系统调用接口直接向堆申请内存和释放内存ObjectPoolSpan _spanPool;//保存页号和span的映射关系为了后续能找到每一个还回来的小对象属于哪一个spanstd::unordered_mapPAGE_ID, Span* _idSpanMap;}; 7.3 PageCache.cpp //静态对象需要在类内声明类外面定义 PageCache PageCache::_sInst;//k代表的是这个span的大小k页 Span* PageCache::NewSpan(size_t k) {assert(k 0);//如果申请的span的大小大于128页则需要直接向堆申请//因为PageCache只有128个有效的哈希桶if (k NPAGES - 1){//向堆申请k页内存void* ptr SystemAlloc(k);Span* kSpan _spanPool.New();//_spanPoll是定长内存池对象直接向堆申请内存//地址转化成页号kSpan-_pageId (PAGE_ID)ptr PAGE_SHIFT;kSpan-_n k;//把页号和Kspan的映射关系放进Map中_idSpanMap[kSpan-_pageId] kSpan;return kSpan;}else{//如果PageCache第k个位置的哈希桶上有k页大小的span则直接返回一个spanif (!_spanLists[k].Empty()){Span* kSpan _spanLists[k].PopFront();//把kSpan的页号和对应的Span*的映射关系存放到哈希桶中去,方便//CentralCache回收小块内存时查找对应的span//kSpan代表的是一个k页大小的Span的大块内存kSpan-_pageId//代表这个大块内存的起始地址有k页所以这k页映射到的都是这个Span// //这里曾经没有存映射关系导致归还小内存块的时候找不到所属的span细节for (PAGE_ID i 0; i kSpan-_n; i){_idSpanMap[kSpan-_pageId i] kSpan;}return kSpan;}//走到这里说明PageCache第k个位置的哈希桶没有k页大小的span则需要遍历//后面的大于k页的哈希桶找到了一个n页大小的span就把这个span切分成一个// k页大小的span和一个n-k页大小的spank页的返回n-k页的挂到对应的哈希桶中//遍历后面的哈希桶for (size_t i k 1; i NPAGES; i){//找到了一个不为空的i页的哈希桶就对它进行切分if (!_spanLists[i].Empty()){//k页的spanSpan* kSpan _spanPool.New();//n页的spanSpan* nSpan _spanLists[i].PopFront();//把这个i页大小的span拿出来进行切分//开始把一个n页的span切分成一个k页的span和一个n-k页的span// //从nSpan的头上切k页给kSpan所以kSpan的页号就是nSpan的页号kSpan-_pageId nSpan-_pageId;kSpan-_n k;//kSpan的页数是k//被切分以后nSpan的页号需要k页因为头nSpan的头k页已经切分给了kSpannSpan-_pageId k;nSpan-_n - k;//nSpan的页数要-k页因为nSpan被切走了k页//把kSpan的页号和对应的Span*的映射关系存放到哈希桶中去,方便// CentralCache回收小块内存时查找对应的span//kSpan代表的是一个k页大小的Span的大块内存kSpan-_pageId//代表这个大块内存的起始地址有k页所以这k页映射到的都是这个Spanfor (PAGE_ID i 0; i kSpan-_n; i){_idSpanMap[kSpan-_pageId i] kSpan;}//nSpan被切分后的首页和尾页的页号和nspan的映射关系也需要保存起来//以便后续合并因为合并的方式是前后页合并往前找肯定找到的是一个span的//最后一页往后找一定找的是一个span的第一页所以挂在PageCache对应哈希桶//的span的第一页和最后一页与span的关系也需要保存起来_idSpanMap[nSpan-_pageId] nSpan;_idSpanMap[nSpan-_pageId nSpan-_n - 1] nSpan;//把剩余的n-k页的span头插到对应下标的哈希桶中nSpan-_n已经是改过的了不用再-k_spanLists[nSpan-_n].PushFront(nSpan);return kSpan;}}//走到这里说明前面的NPAGES个哈希桶中都没有Span(例如第一次申请内存时)//则需要向堆申请一个128页大小的span大块内存挂到对应的哈希桶中void* ptr SystemAlloc(NPAGES - 1);Span* bigSpan _spanPool.New();bigSpan-_pageId (PAGE_ID)ptr PAGE_SHIFT;//内存的地址需要转换成页号映射到对应的哈希桶中bigSpan-_n NPAGES - 1;//大块内存的页数描述这个bigspan的大小//把NPAGES-1页大小的span头插到对应NPAGES-1号桶中去_spanLists[bigSpan-_n].PushFront(bigSpan);//本质是运用了复用的设计避免代码中出现重复的逻辑return NewSpan(k);}}Span* PageCache::MapObjectToSpan(void* obj) {//计算出obj对应的页号PAGE_ID id (PAGE_ID)obj PAGE_SHIFT;//访问_idSpanMap的时候需要加锁避免线程安全的问题//这里使用C11的RAII锁出了这个函数这把锁会自动解掉std::unique_lockstd::mutex lock(_pageMtx);//通过页号查找该内存块对应的是哪一个spanauto ret _idSpanMap.find(id);if (ret ! _idSpanMap.end()){return ret-second;}else{assert(false);return nullptr;} }//CentralCache把span还回来给PageCache void PageCache::ReleaseSpanToPageCache(Span* span) {//如果span的页数大于128页则说明这个span是从堆上直接申请的//直接释放给堆即可不能挂到PageCache的哈希桶中因为PageCache一个只有128个桶if (span-_n NPAGES - 1){void* ptr (void*)(span-_pageId PAGE_SHIFT);SystemFree(ptr);_spanPool.Delete(span);return;}while (1){//找前一页的span看是否能够和当前页合并如果能则循环向前合并直到不能合并为止PAGE_ID prevId span-_pageId - 1;auto ret _idSpanMap.find(prevId);//_idSpanMap中没找到前一页和对应span说明前一页的内存没有被申请结束合并if (ret _idSpanMap.end()){break;}Span* prevSpan ret-second;//如果前一页对应的span在CentralCache中正在被使用结束合并if (prevSpan-_isUse true){break;}//如果和前一页合并之后会超过哈希桶的最大的映射返回结束合并if (prevSpan-_n span-_n NPAGES - 1){break;}//合并span和prevSpanspan-_pageId prevSpan-_pageId;span-_n prevSpan-_n span-_n;//合并之后需要把prevSpan在对应的哈希桶中删除掉_spanLists[prevSpan-_n].Erase(prevSpan);//因为prevSpan已经被合并到了span中所以prevSpan对应的内存可以delete掉了_spanPool.Delete(prevSpan);}while (1){//找span的下一个span的起始页号PAGE_ID nextId span-_pageId span-_n;auto ret _idSpanMap.find(nextId);if (ret _idSpanMap.end()){break;}Span* nextSpan ret-second;if (nextSpan-_isUse true){break;}if (nextSpan-_n span-_n NPAGES - 1)//曾经写成NPAGES1了{break;}//span的起始页号不变页数相加span-_n span-_n nextSpan-_n;//合并之后需要把prevSpan在对应的哈希桶中删除掉_spanLists[nextSpan-_n].Erase(nextSpan);_spanPool.Delete(nextSpan);}//合并得到的新的span需要挂到对应页数的哈希桶中_spanLists[span-_n].PushFront(span);//在PageCache中的span要设置为false好让后面相邻的span来合并span-_isUse false;//为了方便后续的合并需要把span的起始页号和尾页号和span建立映射关系_idSpanMap[span-_pageId] span;_idSpanMap[span-_pageId span-_n - 1] span;} 以上就是高并发内存池三层模型的核心部分后面的文章是对该高并发内存池的性能测试以及针对性能的瓶颈区做出相应的优化策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/919691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完整教程:iOS 混淆与反调试反 Hook 实战,运行时防护、注入检测与安全加固流程

完整教程:iOS 混淆与反调试反 Hook 实战,运行时防护、注入检测与安全加固流程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-f…

3.WPF - 依赖属性 - 实践

3.WPF - 依赖属性 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &q…

Attention进阶史(MHA, MQA, GQA, MLA)

在深度学习领域,注意力机制(Attention Mechanism)自诞生以来便成为推动自然语言处理和计算机视觉等任务发展的核心动力。从最初的多头注意力(MHA)到如今的高效变体,如多查询注意力(MQA)、分组查询注意力(GQA)…

实用指南:AI编程时代的变革:Replit CEO对话深度解析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025北京个性旅行自由行口碑推荐北京汇通清源国际旅游公司,满足独特需求,自由随心

2025年,想要在北京开启一场个性十足的自由行?那就一定要了解一下北京汇通清源国际旅游公司。这家成立于2014年的旅游公司,注册资本300万元人民币,坐落于北京市朝阳区,业务广泛,涵盖全北京各个区域的旅游业务,包…

广州专业做网站多少钱加速游戏流畅的软件

今天我来讲一下在Linux下各环境的搭建,主要就讲一下jdk、MySQL、和一个代理服务器nginx 1、 jdk的安装配置 1)卸载自带openjdk 当我们拿到一个全新的ECS的时候上面有的会自带一个openjdk,但是我们一般不会用这个,所以在这里我们会先卸载这个自…

电子商务网站开发文档在线qq登录无需下载

选择、插入、冒泡三种算是最典型的排序算法了,空间复杂度都为O(1) 选择排序时间复杂度跟初始数据顺序无关,O(n2),而且还不稳定; 插入排序时间复杂度跟初始数据顺序有关最好O(n),最坏O(n2),稳定 冒泡排序时间复杂度跟初始数据顺序有…

网站 自定义表单招聘网站开发背景

陆游的《诗人苦学说》:从藻绘到“功夫在诗外” 今天看万维钢的《万万没想到》一书,看到陆游的功夫在诗外的句子,特意去查找这首诗的原文。故而有此文。 我国学人还往往过分强调“功夫在诗外”这句陆游的名言,认为提升综合素质是一…

学做网站多少钱百度关键词搜索广告的优缺点

目录 引言整体结构图方法介绍训练vision vocabulary阶段PDF数据目标检测数据 训练Vary-toy阶段Vary-toy结构数据集情况 引言 论文:Small Language Model Meets with Reinforced Vision Vocabulary Paper | Github | Demo 说来也巧,之前在写论文阅读&…

2025推拉门品牌推荐榜:聚焦玻璃推拉门,钛镁合金推拉门选择指南

随着家居品质需求升级,推拉门已成为阳台封窗、厨房隔断等场景的核心配置,但市场现状却让消费者陷入选择困境:部分产品宣称的隔音节能性能与实际体验严重不符,五金件易损耗、密封失效等质量问题频发,售后 “踢皮球…

C++中函数的分文件编写

C++中函数的分文件编写Posted on 2025-09-27 16:40 steve.z 阅读(0) 评论(0) 收藏 举报1、创建 .h 头文件 2、创建 .cpp 源文件 3、在 .h 头文件中,编写函数声明 4、在 .cpp 源文件中,编写函数定义 test.h #inc…

PyTorch详细安装指南与常见问题解决强大的方案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

做网站大概一个月多少工资政务信息网站建设方案

作者 | butterfly100来源 | cnblogs.com/butterfly100/p/9034281.html一. 数据切分关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索…

礼县建设局网站重庆公路工程建设信息管理系统

加入大语言模型(LLM) 接着,需要在聊天机器人中加入 LLM。这样,用户就可以和聊天机器人开展对话了。本示例中,我们将使用 OpenAI ChatGPT 背后的模型服务:GPT-3.5。 聊天记录 为了使 LLM 回答更准确,我们需要存储用户和机器人的聊天记录,并在查询时调用这些记录,可以用…

【Azure APIM】APIM在上传文件的时候,请求的Payload是否有文件大小的限制呢?

APIM在上传文件的时候,请求的Payload是否有文件大小的限制呢?问题描述 使用APIM + App Service的架构对外提供服务,其中一个接口为文件上传。在测试的时候,发现上传超过20MB的内容时候就会遇见报错,而不使用APIM时…

PolarDN PIoTS 简单

PolarD&N PIoTS 简单bluetooth test 一、查看题目附件有一个log文件和一个txt文件。 二、题目分析 根据txt文件提示,使用FrontLine11工具打开log文件使用FrontLine11进行分析,只有command指令才能控制设备,筛选…

图解KV Cache

LLM中下一个token预测 Transformer 生成隐藏状态Transformer 为所有 token 生成隐藏状态。 隐藏状态被投射到词汇空间。 最后一个 token 的 logits 用于生成下一个 token。生成新 token 的输出要生成新 token,我们只需…

什么软件网站好网站首页有被收录就是最近没有被抓取是怎么回事

在视频网站上看电影追剧,已经成为了大众生活中必不可少的一部分。为了保护自家视频的版权,很多平台都禁止用户下载会员视频。其实只要掌握了正确的方法,一样可以将会员视频下载到本地保存。那么有关有什么可以下载网页视频的浏览器&#xff0…

4-3〔O҉S҉C҉P҉ ◈ 研记〕❘ WEB应用攻击▸本地资料涵盖漏洞-A

4-3〔O҉S҉C҉P҉ ◈ 研记〕❘ WEB应用攻击▸本地资料涵盖漏洞-A2025-09-27 16:29 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !im…