高并發內存池(centralcache)[2]

Central cache

threadcache是每個線程獨享,而centralcache是多線程共享,需要加鎖(桶鎖)一個桶一個鎖
在這里插入圖片描述
在這里插入圖片描述
解決外碎片問題:內碎片:申請大小超過實際大小;外碎片:空間碎片不連續,導致無法申請大塊空間

span

在存儲管理中,"span"是一個術語,用于描述連續的內存塊或磁盤塊的范圍。

在內存管理中,一個span通常是一系列連續的內存頁或內存塊,它們被分配給一個進程或數據結構。一個span的大小可以根據需求而變化,通常是以頁的大小為單位進行分配。

在磁盤管理中,一個span通常是一系列連續的磁盤塊,它們被分配給一個文件或數據結構。一個span的大小可以根據需求而變化,通常是以磁盤塊的大小為單位進行分配。

使用span的好處是可以提高內存或磁盤的利用率,避免了碎片化的問題。通過分配連續的span,可以更有效地利用存儲資源,并提高數據的讀寫性能。
在這里插入圖片描述
span設計成雙向鏈表 帶頭雙向循環,插入刪除更加高效
32位機器和64位機器的頁數不同!!!!!!!!!
在這里插入圖片描述
使用條件編譯在預處理階段解決

#ifdef _WIN32typedef size_t PAGE_ID;
#elif  _WIN64typedef unsigned long long PAGE_ID;
#endif

但是在64位下還是會有問題
在這里插入圖片描述
所有要調換順序

#ifdef _WIN64typedef unsigned long long PAGE_ID;
#elif  _WIN32typedef size_t PAGE_ID;
#endif
// 管理多個連續頁大塊內存跨度結構
struct Span
{PAGE_ID _pageId = 0; // 大塊內存起始頁的頁號size_t  _n = 0;      // 頁的數量Span* _next = nullptr;	// 雙向鏈表結構Span* _prev = nullptr;size_t _useCount = 0; // 切好小塊內存,被分配給thread cache的計數void* _freeList = nullptr;  // 切好的小塊內存的自由鏈表
};// 帶頭雙向循環鏈表 
class SpanList
{
public:SpanList(){_head = new Span;_head->_next = _head;_head->_prev = _head;}Span* Begin(){return _head->_next;}Span* End(){return _head;}bool Empty(){return _head->_next == _head;}void PushFront(Span* span){Insert(Begin(), span);}Span* PopFront(){Span* front = _head->_next;Erase(front);return front;}void Insert(Span* pos, Span* newSpan){assert(pos);assert(newSpan);Span* prev = pos->_prev;// prev newspan posprev->_next = newSpan;newSpan->_prev = prev;newSpan->_next = pos;pos->_prev = newSpan;}void Erase(Span* pos){assert(pos);assert(pos != _head); //不能刪除哨兵位Span* prev = pos->_prev;Span* next = pos->_next;prev->_next = next;next->_prev = prev;//不去刪除,因為空間是要還給下一層}private:Span* _head;
public:std::mutex _mtx; // 桶鎖
};

CentralCache類

只能有一個,所以采用單例模式

// 單例模式
class CentralCache
{
public:static CentralCache* GetInstance(){return &_sInst;}// 獲取一個非空的spanSpan* GetOneSpan(SpanList& list, size_t byte_size);// 從中心緩存獲取一定數量的對象給thread cachesize_t FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size);private:SpanList _spanLists[NFREELIST];private:CentralCache(){}CentralCache(const CentralCache&) = delete;static CentralCache _sInst;
};

threadcache從centralcache中獲取span

首先明確一次獲取的數量

// 一次thread cache從中心緩存獲取多少個static size_t NumMoveSize(size_t size){assert(size > 0);// [2, 512],一次批量移動多少個對象的(慢啟動)上限值// 小對象一次批量上限高// 小對象一次批量上限低int num = MAX_BYTES / size;if (num < 2)num = 2;if (num > 512)num = 512;return num;}

實現獲取,逐步遞增。獲取一個時直接返回就行,不是一個時先將其串聯起來再返回頭

void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{// 慢開始反饋調節算法// 1、最開始不會一次向central cache一次批量要太多,因為要太多了可能用不完// 2、如果你不要這個size大小內存需求,那么batchNum就會不斷增長,直到上限// 3、size越大,一次向central cache要的batchNum就越小// 4、size越小,一次向central cache要的batchNum就越大size_t batchNum = min(_freeLists[index].MaxSize(), SizeClass::NumMoveSize(size));if (_freeLists[index].MaxSize() == batchNum){_freeLists[index].MaxSize() += 1;}void* start = nullptr;void* end = nullptr;size_t actualNum = CentralCache::GetInstance()->FetchRangeObj(start, end, batchNum, size);assert(actualNum > 0);if (actualNum == 1){assert(start == end);return start;}else{_freeLists[index].PushRange(NextObj(start), end);return start;}
}

完善自由鏈表

//管理切分好的小對象的自由鏈表
class FreeList
{
public:void Push(void* obj){assert(obj);// 頭插//*(void**)obj = _freeList;NextObj(obj) = _freeList;_freeList = obj;}void PushRange(void* start, void* end){NextObj(end) = _freeList;_freeList = start;}void* Pop(){assert(_freeList);// 頭刪void* obj = _freeList;_freeList = NextObj(obj);return obj;}bool Empty(){return _freeList == nullptr;}size_t& MaxSize(){return _maxSize;}
private:void* _freeList;size_t _maxSize = 1;
};

實現FetchRangobj

// 從中心緩存獲取一定數量的對象給thread cache
size_t CentralCache::FetchRangeObj(void*& start, void*& end, size_t batchNum, size_t size)
{size_t index = SizeClass::Index(size);_spanLists[index]._mtx.lock();Span* span = GetOneSpan(_spanLists[index], size);assert(span);assert(span->_freeList);// 從span中獲取batchNum個對象// 如果不夠batchNum個,有多少拿多少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;span->_useCount += actualNum;_spanLists[index]._mtx.unlock();return actualNum;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42540.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42540.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42540.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

跨境電商ERP源碼大揭秘,讓你少走彎路

本文將深入介紹跨境電商ERP源碼的重要性以及如何選擇和應用它們&#xff0c;讓你的電商業務更高效、順暢。 跨境電商ERP源碼的重要性 提升管理效率 跨境電商運營面臨著眾多挑戰&#xff0c;如訂單管理、庫存追蹤和財務報告等。跨境電商ERP源碼能夠集成這些功能&#xff0c;幫…

自動駕駛,一次道阻且長的遠征|數據猿直播干貨分享

?數據智能產業創新服務媒體 ——聚焦數智 改變商業 在6月的世界人工智能大會上&#xff0c;馬斯克在致辭中宣稱&#xff0c;到2023年底&#xff0c;特斯拉便可實現L4級或L5級的完全自動駕駛&#xff08;FSD&#xff09;。兩個月之后&#xff0c;馬斯克又在X社交平臺上發言&am…

java面試強基(16)

目錄 clone方法的保護機制 Java中由SubString方法是否會引起內存泄漏&#xff1f; Java中提供了哪兩種用于多態的機制? 程序計數器(線程私有) 如何判斷對象是否是垃圾&#xff1f; clone方法的保護機制 clone0方法的保護機制在Object中是被聲明為 protected的。以User…

1000元到3000元預算的阿里云服務器配置大全

1000元、2000元或3000元預算能夠買的阿里云服務器配置有哪些&#xff1f;可以選擇ECS通用算力型u1云服務器、ECS計算型c7或通用型g7實例規格&#xff0c;當然&#xff0c;如果選擇輕量應用服務器的話&#xff0c;更省錢&#xff0c;阿里云百科分享1000-3000元預算能買的阿里云服…

三、Dubbo 注冊中心

三、Dubbo 注冊中心 3.1 注冊中心概述 主要作用 動態加入&#xff1a;服務提供者通過注冊中心動態地把自己暴露給其他消費者動態發現&#xff1a;消費者動態地感知新的配置、路由規則和新的服務提供者動態調整&#xff1a;注冊中心支持參數的動態調整&#xff0c;新參數自動更…

如何用輕葉H5制作一份調查問卷

在營銷落地頁中&#xff0c;問卷類H5是一種制作簡單&#xff0c;易于傳播的落地頁&#xff0c;通過精巧的設計和嚴密的邏輯設置&#xff0c;問卷類H5的投放效果也是不容小覷的。 問卷類H5在制作中有以下不可缺少的要素&#xff1a; 清晰的標題和簡要的說明 標題應該簡明扼要地…

用pytorch實現AlexNet

AlexNet經典網絡由Alex Krizhevsky、Hinton等人在2012年提出&#xff0c;發表在NIPS&#xff0c;論文名為《ImageNet Classification with Deep Convolutional Neural Networks》&#xff0c;論文見&#xff1a;http://www.cs.toronto.edu/~hinton/absps/imagenet.pdf &#xf…

C語言 常用工具型API ----------strchr()

函數原型 char *strchr(const char *str, int c) 參數 str-- 要被檢索的 C 字符串。 c-- 在 str 中要搜索的字符。 功能 在參數str所指向的字符串中搜索第一次出現字符c&#xff08;一個無符號字符&#xff09;的位置 頭文件 #include <string.h> 返回值 返回一…

【觀察者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實現

簡介 觀察者模式&#xff08;Observer Pattern&#xff09;是一種行為型模式。它定義對象間的一種一對多的依賴關系&#xff0c;當一個對象的狀態發生改變時&#xff0c;所有依賴于它的對象都得到通知并被自動更新。 觀察者模式使用三個類Subject、Observer和Client。Subject…

PCI 總線樹BUS 號

在一個處理器系統中&#xff0c;每一個host 主橋都推出一棵PCI 總線樹。 一棵PCI 總線樹中有多少個PCIB bridge , 就含有多少條PCI 總線。 系統軟件在遍歷當前PCI 總線樹時&#xff0c;需要首先對這些PCI 總線進行編號&#xff0c;即初始化PCI 橋的primary, secondary 和Subord…

C++自學: virtual function

使用virtual關鍵字在base class中聲明virtual function。你可以使用指針在derived class中調用和執行virtual function。 “virtual void MakeSound() 0;”這是一個pure virtual function。 有至少一個pure virtual function的class稱為abstract class&#xff0c;所以Instr…

策略梯度方法

策略梯度方法 數學背景 給定一個標量函數 J ( θ ) J\left(\theta\right) J(θ)&#xff0c;利用梯度上升法&#xff0c;使其最大化&#xff0c;此時的 π θ \pi_\theta πθ?就是最優策略。 θ t 1 θ t α ? θ J ( θ t ) \theta_{t1}\theta_t\alpha \nabla_\theta…

Element Plus el-table 數據為空時自定義內容【默認為 No Data】

1. 通過 Table 屬性設置 <div class"el-plus-table"><el-table empty-text"暫無數據" :data"tableData" style"width: 100%"><el-table-column prop"date" label"Date" width"180" /&g…

系統架構設計師---OSI七層協議

目錄 OSI七層協議 各層主要功能和詳細說明 Internet協議的主要協議及其層次關系

常用的請求 Content-Type 類型

application/json&#xff1a;用于發送 JSON 格式的數據&#xff0c;常用于 RESTful API 請求中。 application/x-www-form-urlencoded&#xff1a;在 POST 請求中以 URL 編碼(key-value 對)的方式發送表單數據。 multipart/form-data&#xff1a;用于同時上傳文件和其他表單…

vue + el-table 表格數據導出為excel表格

下載依賴 npm install --save xlsx file-saver引入插件 import * as XLSX from xlsx; import FileSaver from "file-saver";完整代碼 <template><div class"administrativeCase-container"><div class"content-box"><di…

Java后端實現不用pagehelper。手寫分頁如何實現?

Java后端實現不用pagehelper。手寫分頁如何實現? 如果你不使用PageHelper這樣的分頁插件&#xff0c;你可以手動實現分頁邏輯。下面是一個使用Java后端手寫分頁的示例&#xff1a; 首先&#xff0c;確定每頁顯示的數據量和當前頁碼。 int pageSize 10; // 每頁顯示的數據量…

移動通信系統的LMS自適應波束成形技術matlab仿真

目錄 1.算法運行效果圖預覽 2.算法運行軟件版本 3.部分核心程序 4.算法理論概述 5.算法完整程序工程 1.算法運行效果圖預覽 2.算法運行軟件版本 matlab2022a 3.部分核心程序 ..................................................................... idxx0; while idxx&…

Spring Bean的生命周期總結(包含面試題)

目錄 一、Bean的初始化過程 1. 加載Spring Bean 2. 解析Bean的定義 3. Bean屬性定義 4. BeanFactoryPostProcessor 擴展接口 5. 實例化Bean對象 6. Aware感知 7. 初始化方法 8. 后置處理 9. destroy 銷毀 二、Bean的單例與多例模式 2.1 單例模式&#xff08;Sin…