中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

煙臺h5網(wǎng)站建設(shè)公司投稿網(wǎng)

煙臺h5網(wǎng)站建設(shè)公司,投稿網(wǎng),免費(fèi)建設(shè)獨(dú)立域名網(wǎng)站,新加坡網(wǎng)站開發(fā)公司目錄 定長內(nèi)存池設(shè)計(jì)設(shè)計(jì)思路具體實(shí)現(xiàn)定長內(nèi)存池初始化T*New()申請內(nèi)存代碼 void Delete(T* obj)回收內(nèi)存代碼 設(shè)計(jì)的總代碼測試代碼 Objectpool.h文件代碼test.cpp文件代碼拓展windows和Linux下如何直接向堆申請頁為單位的大塊內(nèi)存: 感謝各位大佬對我的支持,如果我…

目錄

  • 定長內(nèi)存池設(shè)計(jì)
    • 設(shè)計(jì)思路
      • 具體實(shí)現(xiàn)
        • 定長內(nèi)存池初始化
          • T*New()申請內(nèi)存
            • 代碼
          • void Delete(T* obj)回收內(nèi)存
            • 代碼
          • 設(shè)計(jì)的總代碼
          • 測試代碼
  • Objectpool.h文件代碼
  • test.cpp文件代碼
  • 拓展windows和Linux下如何直接向堆申請頁為單位的大塊內(nèi)存:

感謝各位大佬對我的支持,如果我的文章對你有用,歡迎點(diǎn)擊以下鏈接
🐒🐒🐒 個(gè)人主頁
🥸🥸🥸 C語言
🐿?🐿?🐿? C語言例題
🐣🐣🐣 python
🐓🐓🐓 數(shù)據(jù)結(jié)構(gòu)C語言
🐔🐔🐔 C++
🐿?🐿?🐿? 文章鏈接目錄
🤠🤠🤠 高并發(fā)內(nèi)存池項(xiàng)目

定長內(nèi)存池設(shè)計(jì)

設(shè)計(jì)思路

申請一大塊內(nèi)存,用一個(gè)指針指向申請的內(nèi)存,這里的難點(diǎn)是內(nèi)存釋放,因?yàn)槲覀兩暾埖氖且粔K很大的內(nèi)存,而使用的時(shí)候都是將這一大塊內(nèi)存切成一小塊一小塊的用,而用完后釋放我們不可以直接將他還給系統(tǒng),因?yàn)獒尫诺膬?nèi)存太小了,如果還給系統(tǒng)就會(huì)出現(xiàn)內(nèi)存碎片的問題,所以我們是要將需要釋放的內(nèi)存管理起來,當(dāng)他們都釋放后再歸還內(nèi)存,這里的管理方式就是用一個(gè)鏈表將內(nèi)存管理起來
在這里插入圖片描述
由于是定長內(nèi)存池,這里的定長就是切固定大小的內(nèi)存

具體實(shí)現(xiàn)

定長內(nèi)存池初始化

首先我們需要一個(gè)類

class Objectpool
{};

由于是定長內(nèi)存池,所以類里面一點(diǎn)要有一個(gè)指針指向申請的內(nèi)存空間,為了方便切割內(nèi)存我們使用char*_memory,因?yàn)閏har是可以精確到1個(gè)字節(jié)1個(gè)字節(jié)的切割比較方便,如果是int的話那么我們要切割的長度就是4的倍數(shù)
此外因?yàn)樯暾垉?nèi)存是固定的我們可以用非類型的模版參數(shù)template<size_t N>表示我們申請的內(nèi)存是一個(gè)固定大小為N
當(dāng)然我們也可以用template表示ObjectPool每次獲取的對象都是一個(gè)T對象,T的大小是固定的,這里我們選擇的是用template

template<class T>
class ObjectPool
{char* _memory=nullptr;
};

我們還需要考慮內(nèi)存回收
在這里插入圖片描述
當(dāng)我們需要切割內(nèi)存時(shí)_memory需要往后移動(dòng)
在這里插入圖片描述

在這里插入圖片描述
當(dāng)切割后的內(nèi)存用完后需要回收我們需要用一個(gè)鏈表將他們串起來
在這里插入圖片描述
在這里插入圖片描述
可是現(xiàn)在有一個(gè)問題我們應(yīng)該怎么樣才能將他們串起來,我們是否需要再定義一個(gè)結(jié)構(gòu)體將他們鏈接起來呢?

其實(shí)是不需要的,我們可以直接在內(nèi)存當(dāng)中修改,將后面的內(nèi)存塊地址存到前一個(gè)內(nèi)存塊當(dāng)中,但是這里有一個(gè)要求就是32位下的指針大小是4個(gè)字節(jié),而64位下的指針大小是8個(gè)字節(jié),也就意味著當(dāng)我們要存一個(gè)內(nèi)存塊的空間時(shí),32位下內(nèi)存塊至少要有4個(gè)字節(jié),而64位則至少要有8個(gè)字節(jié)

在32位下對于一個(gè)內(nèi)存塊有100字節(jié)我們則需要將他的頭4個(gè)字節(jié)進(jìn)行修改保存下一塊內(nèi)存的地址
在這里插入圖片描述

T*New()申請內(nèi)存

申請內(nèi)存我們需要先看_memory是否為空,如果_memory為空的話那么就需要申請內(nèi)存

T* New()
{if (_memory==nullptr)//剩余內(nèi)存不夠一個(gè)對象大小是重新開大塊空間{_memory =(char*) malloc(128 * 1024);//128kbif (_memory == nullptr){throw std::bad_alloc();}}T* obj = (T*)_memory;_memory += sizeof(T);return obj;
}

如果申請后_memory仍為空那么就拋異常,反之就讓一個(gè)對象obj指向申請內(nèi)存的空間
_memory += sizeof(T)就表示的切割空間,讓_memory切割 sizeof(T)大小的空間
在這里插入圖片描述

這里有一個(gè)問題就是_memory走到最后的時(shí)候,如果_memory繼續(xù)+= sizeof(T)就會(huì)造成越界,因?yàn)樯暾埖膬?nèi)存以及用完了,而_memory現(xiàn)在在訪問的是別的空間
在這里插入圖片描述
在這里插入圖片描述
為了解決這個(gè)問題我們還需要有一個(gè)remainBytes去記錄還剩多少空間,當(dāng)remainBytes<sizeof(T)的時(shí)候就意味著剩下的空間以及不足以支持我們繼續(xù)切割了,可能需要重新申請一塊空間

為什么是可能需要重新申請一塊空間呢,因?yàn)開freeList是回收釋放的內(nèi)存,如果_freeList中有回收了的內(nèi)存,那么這些內(nèi)存是可以繼續(xù)重復(fù)利用的
所以一開始需要一個(gè)指針next保存_freeList前面記錄下來的位置,然后讓obj指向_freeList,再讓_freeList=next

	T* obj = nullptr;if (_freeList){void* next = *((void**))_freeList);obj = (T*)_freeList;//因?yàn)閛bj是T*,所以_freeList也要強(qiáng)轉(zhuǎn)_freeList = next;}

void* next = * ((void**))_freeList)這段代碼會(huì)在下面部分解釋
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
還有一個(gè)問題就是sizeof(T)大小問題,因?yàn)檫@是一個(gè)類模版,如果T是char類型的話他的內(nèi)存是小于4個(gè)字節(jié)的,int類型的話也就剛好4個(gè)字節(jié),但是在64位下是不夠的,所以需要判斷sizeof(T) < sizeof(void*) ,表示T的內(nèi)存大小是否小于一個(gè)指針,如果小于的話就要更改切割內(nèi)存的大小
最后我們還需要對我們創(chuàng)造的對象進(jìn)行初始化
這里用定位new顯示調(diào)用T的構(gòu)造函數(shù)初始化new(obj)T

代碼
	T* New(){T* obj = nullptr;if (_freeList){void* next = *((void**))_freeList);obj =(T*) _freeList;_freeList = next;}else{if (_remainBytes < sizeof(T))//剩余內(nèi)存不夠一個(gè)對象大小是重新開大塊空間{_remainBytes = 128 * 1024;_memory = (char*)malloc(_remainBytes);//128kbif (_memory == nullptr){throw std::bad_alloc();}}obj = (T*)_memory;size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);//因?yàn)門是一個(gè)類模版,當(dāng)T是char或int時(shí)可能會(huì)導(dǎo)致內(nèi)存不足以存儲一個(gè)地址_memory += objSize;_remainBytes -= objSize;}new(obj)T;//定位new顯示調(diào)用T的構(gòu)造函數(shù)初始化return obj;}
void Delete(T* obj)回收內(nèi)存

在最開始的時(shí)候_freeList是指向的空
在這里插入圖片描述
當(dāng)?shù)谝淮斡锌臻g回收時(shí),我們要讓空間的前4個(gè)字節(jié)存空地址,具體辦法就是讓傳入的指針強(qiáng)轉(zhuǎn)成int*,那么我們對int進(jìn)行解引用將前4個(gè)字節(jié)更改為nullptr就可以實(shí)現(xiàn)了
在這里插入圖片描述
但是這里有一個(gè)問題就是int
只有4個(gè)字節(jié),這種方法只適用于32位下,在64位下是不行的
當(dāng)然我們可以用if語句判斷一個(gè)指針的大小,然后再進(jìn)行細(xì)分也是可以的
下面有更簡單的方式就是將obj強(qiáng)轉(zhuǎn)成void**,也就是二級指針(其他類型的二級指針也是可以的,主要用的就是二級指針轉(zhuǎn)換成一級指針的空間大小是4/8個(gè)字節(jié)),然后我們對他解引用,*(void**)obj = nullptr

上面是解決第一次內(nèi)存塊回收的問題,下面是解決多次回收的問題
在這里插入圖片描述

多個(gè)內(nèi)存塊回收我們選擇用頭插的方式串起來,因?yàn)槲膊逍侍?br /> 在這里插入圖片描述
首先還是要讓新的內(nèi)存塊保存_freeList指向的地址,然后讓_freeList指向新的內(nèi)存塊
在這里插入圖片描述
在這里插入圖片描述

void Delete(T* obj)
{if (_freeList==nullptr){_freeList = obj;*(void**)obj = nullptr;}else{*(void**)obj = _freeList;_freeList = obj;}
}

我們發(fā)現(xiàn)上面代碼中

*(void**)obj = _freeList;_freeList = obj;

這段代碼是適用于所有情況的
一開始_freeList=nullptr
在這里插入圖片描述
讓obj前4/8個(gè)字節(jié)保存_freeList
在這里插入圖片描述
然后讓_freeList指向obj
在這里插入圖片描述
即使有新回收的也是適用的
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

代碼
void Delete(T* obj)
{obj->~T();//顯示調(diào)用析構(gòu)函數(shù)*(void**)obj = _freeList;_freeList = obj;
}
設(shè)計(jì)的總代碼
template<class T>
class ObjectPool
{
public:T* New(){T* obj = nullptr;if (_freeList){void* next = *((void**)_freeList);obj =(T*) _freeList;_freeList = next;}else{if (_remainBytes < sizeof(T))//剩余內(nèi)存不夠一個(gè)對象大小是重新開大塊空間{_remainBytes = 128 * 1024;_memory = (char*)malloc(_remainBytes);//128kbif (_memory == nullptr){throw std::bad_alloc();}}obj = (T*)_memory;size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);_memory += objSize;_remainBytes -= objSize;}new(obj)T;return obj;}void Delete(T* obj){obj->~T();*(void**)obj = _freeList;_freeList = obj;}
private:char* _memory = nullptr;//指向大塊內(nèi)存的指針void* _freeList = nullptr;//還回過程中鏈接的自由鏈表頭指針size_t _remainBytes = 0;//大塊內(nèi)存切割過程中的剩余字節(jié)數(shù)
};
測試代碼
struct TreeNode
{int _val;TreeNode* _left;TreeNode* _right;TreeNode():_val(0), _left(nullptr), _right(nullptr){}
};
void TestObjectPool()
{// 申請釋放的輪次const size_t Rounds = 5;// 每輪申請釋放多少次const size_t N = 100000;std::vector<TreeNode*> v1;v1.reserve(N);size_t begin1 = clock();for (size_t j = 0; j < Rounds; ++j){for (int i = 0; i < N; ++i){v1.push_back(new TreeNode);}for (int i = 0; i < N; ++i){delete v1[i];}v1.clear();}size_t end1 = clock();std::vector<TreeNode*> v2;v2.reserve(N);ObjectPool<TreeNode> TNPool;size_t begin2 = clock();for (size_t j = 0; j < Rounds; ++j){for (int i = 0; i < N; ++i){v2.push_back(TNPool.New());}for (int i = 0; i < N; ++i){TNPool.Delete(v2[i]);}v2.clear();}size_t end2 = clock();cout << "new cost time:" << end1 - begin1 << endl;cout << "object pool cost time:" << end2 - begin2 << endl;
}

Objectpool.h文件代碼

#include<iostream>
#include<vector>
#include<time.h>
using std::cout;
using std::endl;
template<class T>
class ObjectPool
{
public:T* New(){T* obj = nullptr;if (_freeList){void* next = *((void**)_freeList);obj =(T*) _freeList;_freeList = next;}else{if (_remainBytes < sizeof(T))//剩余內(nèi)存不夠一個(gè)對象大小是重新開大塊空間{_remainBytes = 128 * 1024;_memory = (char*)malloc(_remainBytes);//128kbif (_memory == nullptr){throw std::bad_alloc();}}obj = (T*)_memory;size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);_memory += objSize;_remainBytes -= objSize;}new(obj)T;return obj;}void Delete(T* obj){obj->~T();*(void**)obj = _freeList;_freeList = obj;}
private:char* _memory = nullptr;//指向大塊內(nèi)存的指針void* _freeList = nullptr;//還回過程中鏈接的自由鏈表頭指針size_t _remainBytes = 0;//大塊內(nèi)存切割過程中的剩余字節(jié)數(shù)
};
struct TreeNode
{int _val;TreeNode* _left;TreeNode* _right;TreeNode():_val(0), _left(nullptr), _right(nullptr){}
};
void TestObjectPool()
{// 申請釋放的輪次const size_t Rounds = 5;// 每輪申請釋放多少次const size_t N = 100000;std::vector<TreeNode*> v1;v1.reserve(N);size_t begin1 = clock();for (size_t j = 0; j < Rounds; ++j){for (int i = 0; i < N; ++i){v1.push_back(new TreeNode);}for (int i = 0; i < N; ++i){delete v1[i];}v1.clear();}size_t end1 = clock();std::vector<TreeNode*> v2;v2.reserve(N);ObjectPool<TreeNode> TNPool;size_t begin2 = clock();for (size_t j = 0; j < Rounds; ++j){for (int i = 0; i < N; ++i){v2.push_back(TNPool.New());}for (int i = 0; i < N; ++i){TNPool.Delete(v2[i]);}v2.clear();}size_t end2 = clock();cout << "new cost time:" << end1 - begin1 << endl;cout << "object pool cost time:" << end2 - begin2 << endl;
}

test.cpp文件代碼

#include"Objectpool.h"
int main()
{TestObjectPool();return 0;  
}

拓展windows和Linux下如何直接向堆申請頁為單位的大塊內(nèi)存:

VirtualAlloc
Linux進(jìn)程分配內(nèi)存的兩種方式–brk() 和mmap()

http://www.risenshineclean.com/news/55467.html

相關(guān)文章:

  • 武漢 網(wǎng)站制作網(wǎng)絡(luò)優(yōu)化seo是什么工作
  • 相親網(wǎng)站做期貨現(xiàn)貨貴金屬的人產(chǎn)品推廣方案ppt
  • 自己建網(wǎng)站數(shù)據(jù)怎么做石家莊抖音seo
  • 安徽合肥做網(wǎng)站的公司最新熱點(diǎn)新聞
  • 拖拽網(wǎng)站怎么做的小紅書kol推廣
  • 移動(dòng)網(wǎng)站建設(shè)哪家好什么平臺可以打廣告做宣傳
  • 網(wǎng)站建設(shè)分金手指排名十百度網(wǎng)絡(luò)電話
  • 響應(yīng)式制作網(wǎng)站建設(shè)線上教育培訓(xùn)機(jī)構(gòu)十大排名
  • 網(wǎng)站導(dǎo)航圖怎么做百度推廣登錄網(wǎng)站
  • 網(wǎng)站正在建設(shè)中 html源碼快手作品免費(fèi)推廣軟件
  • 海安網(wǎng)站開發(fā)seo教程排名第一
  • 大公司網(wǎng)站色彩設(shè)計(jì)萬網(wǎng)域名查詢官網(wǎng)
  • 做有獎(jiǎng)競猜網(wǎng)站違法嗎網(wǎng)站搭建需要多少錢?
  • 做網(wǎng)站php與python做推廣怎么賺錢
  • 做ppt的軟件模板下載網(wǎng)站有哪些網(wǎng)站建站公司
  • 商丘銷售網(wǎng)站制作自媒體
  • 百度免費(fèi)網(wǎng)站怎樣建設(shè)網(wǎng)絡(luò)推廣的重要性與好處
  • 上海網(wǎng)站建設(shè)公司排名外包接單平臺
  • 葫蘆島建設(shè)信息網(wǎng)站企業(yè)建站都有什么網(wǎng)站
  • 閑魚怎么做釣魚網(wǎng)站廣告資源發(fā)布平臺
  • 網(wǎng)站怎么解析到域名百度地圖網(wǎng)頁版進(jìn)入
  • 徐州專業(yè)網(wǎng)站制作公司網(wǎng)址注冊在哪里注冊
  • 百度搜索seo優(yōu)化技巧寧波seo外包推廣排名
  • 微信內(nèi)部劵網(wǎng)站怎么做長沙百度首頁優(yōu)化排名
  • 個(gè)人建設(shè)網(wǎng)站還要備案么公司網(wǎng)站建設(shè)需要多少錢
  • 推薦個(gè)做兼職的網(wǎng)站做網(wǎng)上推廣
  • 東莞網(wǎng)站建設(shè) 樂云seo小程序推廣方案
  • 東營機(jī)關(guān)建設(shè)網(wǎng)站抖音宣傳推廣方案
  • 教做縫紉的網(wǎng)站關(guān)鍵詞排名提升工具
  • 廣州網(wǎng)站建設(shè)網(wǎng)絡(luò)推廣怎么網(wǎng)站推廣