高并發內存池(定長內存池基礎)

定長內存池的設計

      • 定長內存池
      • 定長內存池的原理講解
      • 代碼實現
            • 定義對象
            • New對象的主要邏輯
            • delete對象的主要邏輯
            • 完整代碼

定長內存池

為什么我們要設計這個定長內存池呢?首先malloc是c標準庫中向堆申請空間的接口,變相的說malloc是普遍性,而我們要實現的高并發內存池是特殊性,是針對某種情況下把效率提高到極致的一種申請空間的方法。在后續我們的項目中也會用到定長內存池,所以定長內存池的設計有兩方面,一是讓我們熟悉一下內存的分配問題,二是他會作為我們的高并發內存池的一個基礎組件。

定長內存池的原理講解

首先我們需要在內存中申請一塊固定大小的空間,如下圖:
在這里插入圖片描述

后面我們考慮如何分配空間以及管理后續的空間。這里我們像系統申請了一大塊空間,如果再有用戶需要申請空間這個時候我們就可以直接從我們管理的那一大塊空間中取出空間,從而避免了重復申請和釋放空間的效率問題。但是這里用戶歸還的空間我們也不能直接還給操作系統,所以我們需要使用一個freelist(自由鏈表)將歸還的空間管理起來

在這里插入圖片描述
在這里插入圖片描述
每次從上面取完空間后,歸還空間我們就直接頭插到鏈表中。下次如果在需要申請,我們就可以直接使用_freelist中的空間直接給到用戶使用。

代碼實現

定義對象

我們先定義一個class ObjectPool類對象

#pragma once
#include<iostream>
using std::endl;
using std::cout;template<class T>
class Object {
public:
private:char* _memory = nullptr; //指向內存池的起始位置size_t _remain = 0;      //內存剩余空間大小void* _freelist = nullptr; //指向自由鏈表的第一個節點的指針
};

這里定義三個私有成員變量,具體用處見上述代碼注釋。

New對象的主要邏輯

首先我們對于空間申請的類,肯定就是new 和 delete兩個重要的接口。我們先來寫new:

T* New()
{T* obj = nullptr; //先頂一個返回的objif (_freelist)    //如果自由鏈表不為空,此時我們直接使用自由鏈表的空間{//這里就相當于鏈表的頭刪void* next = *(void**)_freelist; //定義一個next存儲鏈表下一個節點的地址 obj = (T*)_freelist; //再讓obj指向分配內存的首地址_freelist = next;    //再將自由鏈表連接到下一個節點處}else{if (_remain<sizeof(T))  //如果內存空間剩余大小小于當前類型的大小{//重新像系統申請一塊大空間_remain = 128 * 1024; //更新內存剩余空間大小_memory = (char*)malloc(_remain); //開辟空間if (_memory == nullptr)  //如果_memory為空則報錯{throw std::bad_alloc();}}obj = (T*)_memory;  //obj接收被切割的首地址size_t objsize = sizeof(T) < sizeof(void*) ?  sizeof(void*) : sizeof(T);  //這里為了防止開辟的空間沒有辦法儲存地址,所以如果類型大小小于地址的大小,則開辟地址大小字節的空間,否則開辟類型大小的空間。_memory += objsize; //隨后_memory指向后面的空間_remain -= objsize; //_remain減少//顯示調用一下構造,應對string等這些類型的構造new(obj)T;return obj;}
}
delete對象的主要邏輯

delete就相當于是鏈表的頭插

void Delete(T* obj)
{obj->~T();*(void**)obj = _freelist;_freelist = obj;
}

這里的主要邏輯就結束了,接下來對代碼進行優化一下。
我們這里使用的還是malloc,所以我們還可以完全脫離malloc使用系統調用接口virtualalloc這個接口直接在堆上申請空間,接下來就是完整代碼,還有一段測試的例子我們可以清楚的看到我們的定長內存池在申請同一類型的空間時效率的提升有多夸張。

完整代碼

這里我們使用了條件編譯用來區分windows和Linux中不同的系統調用接口。

#pragma once
#include<iostream>
#include<vector>using std::cout;
using std::endl;#ifdef _WIN32
#include<windows.h>
#else
// 
#endif
// 直接去堆上按頁申請空間
inline static void* SystemAlloc(size_t kpage)
{
#ifdef _WIN32void* ptr = VirtualAlloc(0, kpage << 13, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else// linux下brk mmap等
#endifif (ptr == nullptr)throw std::bad_alloc();return ptr;
}template<class T>
class ObjectPool{
public:T* New(){T* obj = nullptr;if (_freelist)//如果自由鏈表不為空則使用自由鏈表中的空間{void* next = *(void**)_freelist;obj = (T*)_freelist;_freelist = next;}else {if (_remain < sizeof(T)){_remain = 128 * 1024;//_memery = (char*)malloc(_remain);_memery = (char*)SystemAlloc(_remain>>13);if (_memery == nullptr){throw std::bad_alloc();}}obj = (T*)_memery;size_t objsize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);_memery += objsize;_remain -= objsize;}new(obj)T;return obj;}void Delete(T* obj){obj->~T();*(void**)obj = _freelist;_freelist = obj;}private:char* _memery = nullptr;//內存池起始地址size_t _remain = 0; //內存池剩余字節數void* _freelist = nullptr; //自由鏈表起始地址
};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;
}

Debug:在這里插入圖片描述
Release:
在這里插入圖片描述

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

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

相關文章

【VUE3】練習項目——大事件后臺管理

目錄 0 前言 1 準備工作 1.1 安裝pnpm 1.2 創建vue項目 1.3 Eslint & Prettier的配置 1.4 husky 提交代碼檢查 1.5 目錄調整 1.6 VueRouter4 1.6.1 基礎配置 1.6.2 路由跳轉 1.7 引入 Element Plus 組件庫 1.8 Pinia 1.8.1 優化 1.9 封裝請求工具 1.9.1 安…

WebSocket與MQTT

在物聯網&#xff08;IoT&#xff09;領域&#xff0c;?WebSocket和MQTT確實都可以實現實時通信&#xff0c;但它們的核心設計目標、適用場景和角色存在顯著差異。以下是兩者的對比分析&#xff1a; ?1. 協議設計初衷? ?WebSocket? ?目標?&#xff1a;提供瀏覽器與服務器…

Mysql為什么有時候會選錯索引

案例 正常情況 有一個表t ( id, a , b )&#xff0c;id是主鍵索引&#xff0c;a是Normal索引。 正常情況下&#xff0c;針對a進行查詢&#xff0c;可以走索引a 并且查詢的數量和預估掃描行數是差不多的&#xff0c;都是10001行 奇怪的現象 隨著時間的變化&#xff0c;后…

[250414] ArcoLinux 項目宣布逐步結束

目錄 ArcoLinux 項目宣布逐步結束 ArcoLinux 項目宣布逐步結束 備受歡迎的 Arch Linux 發行版 ArcoLinux 近日宣布&#xff0c;其項目將逐步結束。ArcoLinux 以其作為 Linux 教育平臺和提供多種安裝選項&#xff08;從完整桌面環境到最小化基礎安裝&#xff09;而聞名。 核心…

opencv人臉性別年齡檢測

一、引言 在計算機視覺領域&#xff0c;人臉分析是一個熱門且應用廣泛的研究方向。其中&#xff0c;人臉性別年齡檢測能夠自動識別圖像或視頻流中人臉的性別和年齡信息&#xff0c;具有諸多實際應用場景&#xff0c;如市場調研、安防監控、用戶個性化體驗等。OpenCV 作為一個強…

【NLP】 22. NLP 現代教程:Transformer的訓練與應用全景解讀

&#x1f9e0; NLP 現代教程&#xff1a;Transformer的訓練與應用全景解讀 一、Transformer的使用方式&#xff08;Training and Use&#xff09; 如何使用Transformer模型&#xff1f; Transformer 模型最初的使用方式有兩種主要方向&#xff1a; 類似 RNN 編碼-解碼器的架…

Spring Boot 集成 RocketMQ 全流程指南:從依賴引入到消息收發

前言 在分布式系統中&#xff0c;消息中間件是解耦服務、實現異步通信的核心組件。RocketMQ 作為阿里巴巴開源的高性能分布式消息中間件&#xff0c;憑借其高吞吐、低延遲、高可靠等特性&#xff0c;成為企業級應用的首選。而 Spring Boot 通過其“約定優于配置”的設計理念&a…

HTTPS實現安全的關鍵方法及技術細節

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;通過多種技術手段實現數據傳輸的安全性&#xff0c;其核心機制基于SSL/TLS協議&#xff0c;并結合數字證書、加密算法等技術。 SSL&#xff1a;Secure Sockets Layer&#xff0c;安全套接字層 TLS&#xff1a;…

Java【多線程】(8)CAS與JUC組件

目錄 1.前言 2.正文 2.1CAS概念 2.2CAS兩種用途 2.2.1實現原子類 2.2.2實現自旋鎖 2.3缺陷&#xff1a;ABA問題 2.4JUC組件 2.4.1Callable接口 2.4.2ReentrantLock&#xff08;與synchronized對比&#xff09; 2.4.3Semaphore信號量 2.4.4CountDownLatch 3.小結 1…

【Docker】離線安裝Docker

背景 離線安裝Docker的必要性&#xff0c;第一&#xff0c;在目前數據安全升級的情況下&#xff0c;很多外網已經基本不好訪問了。第二&#xff0c;如果公司有對外部署的需求&#xff0c;那么難免會存在對方只有內網的情況&#xff0c;那么我們就要做到學會離線安裝。 下載安…

MecAgent Copilot:機械設計師的AI助手,開啟“氛圍建模”新時代

MecAgent Copilot作為機械設計師的AI助手,正通過多項核心技術推動機械設計進入“氛圍建模”新時代。以下從功能特性、技術支撐和應用場景三方面解析其創新價值: 一、核心功能特性 ??智能草圖生成與參數化建模?? 支持自然語言輸入生成設計草圖和3D模型,如輸入“剖面透視…

MCU屏和RGB屏

一、MCU屏 MCU屏?&#xff1a;全稱為單片機控制屏&#xff08;Microcontroller Unit Screen&#xff09;&#xff0c;在顯示屏背后集成了單片機控制器&#xff0c;因此&#xff0c;MCU屏里面有專用的驅動芯片。驅動芯片如&#xff1a;ILI9488、ILI9341、SSD1963等。驅動芯片里…

7.5 使用MobileNet v3進行圖像的區分

MobileNet v3是Google在2019年提出的輕量級卷積神經網絡結構,旨在提高在移動設備上的速度和準確性,廣泛的用于輕量級網絡。 MobileNet v3-Small的網絡結構如下,它的輸入是224x224的3通道彩色圖片。 使用過程如下: 1.創建模型、修改最終分類數量 #1.創建mobilenet_v3_small…

構建面向大模型訓練與部署的一體化架構:從文檔解析到智能調度

作者&#xff1a;汪玉珠&#xff5c;算法架構師 標簽&#xff1a;大模型訓練、數據集構建、GRPO、自監督聚類、指令調度系統、Qwen、LLaMA3 &#x1f9ed; 背景與挑戰 隨著 Qwen、LLaMA3 等開源大模型不斷進化&#xff0c;行業逐漸從“能跑通”邁向“如何高效訓練與部署”的階…

PostgreSQL技術大講堂 - 第86講:數據安全之--data_checksums天使與魔鬼

PostgreSQL技術大講堂 - 第86講&#xff0c;主題&#xff1a;數據安全之--data_checksums天使與魔鬼 1、data_checksums特性 2、避開DML規則&#xff0c;嫁接非法數據并合法化 3、避開約束規則&#xff0c;嫁接非法數據到表中 4、避開數據檢查&#xff0c;讀取壞塊中的數據…

【機器學習】機器學習筆記

1 機器學習定義 計算機程序從經驗E中學習&#xff0c;解決某一任務T&#xff0c;進行某一性能P&#xff0c;通過P測定在T上的表現因經驗E而提高。 eg&#xff1a;跳棋程序 E&#xff1a; 程序自身下的上萬盤棋局 T&#xff1a; 下跳棋 P&#xff1a; 與新對手下跳棋時贏的概率…

Ubuntu20.04 設置開機自啟

參考&#xff1a; Ubuntu20.04 設置開機自啟_ubuntu進bos系統-CSDN博客

數據庫中存儲過程的流程語句講解

一、流程語句講解 二、總結 一、流程語句講解 1.1 if語句講解 語法&#xff1a; IF condition THENstatements; ELSEIF condition THENstatements; ELSEstatements; END IF; 題目示例&#xff1a; # 判斷成績等級 # 輸入學生的編號,取出學生的第一門課&#xff0c;然后判斷…

kubernetes》》k8s》》ConfigMap 、Secret

configmap官網 ConfigMap是一種 API 對象&#xff0c;使用時&#xff0c; Pods 可以將其用作環境變量、命令行參數或者存儲卷中的配置文件。ConfigMap將配置和Pod解耦&#xff0c;更易于配置文件的更改和管理。ConfigMap 并不提供保密或者加密功能。 如果你想存儲的數據是機密的…

git在IDEA中使用技巧

git在IDEA中使用技巧 merge和rebase 參考&#xff1a;IDEA小技巧-Git的使用 git回滾、強推、代碼找回 參考&#xff1a;https://www.bilibili.com/video/BV1Wa411a7Ek?spm_id_from333.788.videopod.sections&vd_source2f73252e51731cad48853e9c70337d8e cherry pick …