STL庫的記憶體配置器(allocator)

来源:http://www.cnblogs.com/lenomirei/archive/2016/04/06/5357970.html
-Advertisement-
Play Games

正在學習中,如果有錯,還請多多指教,根據不斷的理解,會進行更改,更改之前的樣子都會保留下來,記錄錯誤是最大的進步,嗯嗯! 具有次配置力的SGI空間配置器(SGI是STL的一種版本,也有其他的版本) 這裡我就不貼出來具體成員和介面的實現了,網上可以搜到STL的源碼 C++中,new一個變數可以分為兩個 ...


正在學習中,如果有錯,還請多多指教,根據不斷的理解,會進行更改,更改之前的樣子都會保留下來,記錄錯誤是最大的進步,嗯嗯!

具有次配置力的SGI空間配置器(SGI是STL的一種版本,也有其他的版本)

這裡我就不貼出來具體成員和介面的實現了,網上可以搜到STL的源碼

C++中,new一個變數可以分為兩個階段,1.分配空間 2.調用構造函數;delete變數也分為兩個步驟,1.調用析構函數 2.釋放空間

SGI的alloc將這兩部分分開,讓空間的分配釋放和構造析構由不同的函數調用,區分他們的操作

空間的分配和釋放由alloc::alloclate()  alloc::dealloclate()實現 構造和析構由alloc::construct() alloc::destory()函數負責,他們在頭文件

 1 #include<stl_alloc.h> //負責記憶體空間的配置和釋放 2 #include<stl_construct.h> //負責對象內容的構造和析構 這兩個頭文件都包含在#include<memory>當中

先講一下析構和構造的大概思路  

    • 這裡提到一個概念_type_traits<T>(這是個模板),首先通過value_type()獲得迭代器所指向對象的類型然後使用_type_traits進行類型判別,該對象是否是trivial(無關痛癢的) destructor,我對這裡的理解是,當迭代器所指對象的類型為POD(Plain Old Data)類型(PS:POD類型可以理解為傳統的C語言類型,就是int那一類的)是不需要專門調用析構函數的,等待系統自動釋放int所占用的空間即可,但當迭代器所指對象的類型為string對象(或者是其他你自己寫的類的對象),就不能依靠系統,需要調用專門的析構函數挨個析構。進行類型判別之後,就可以提高工作效率。(destory()對char*等類型也有相應的特化)
    • 構造函數就採用泛式構造,使用new進行構造
  • 下麵講一下我對空間的配置與釋放的理解
    • C++對記憶體配置的基本操作依靠::operator new()和::operator delete()這兩個全局函數,這兩個函數只起到分配和釋放記憶體的作用,並不會調用構造函數和析構函數,他們就相當於C語言中的malloc()和free()函數,SGI正是以malloc()和free()進行空間的管理
    • 為瞭解決記憶體碎片的問題(當不斷地malloc空間時候,找到足夠大小的空間就拿來用,不可避免的的會產生記憶體碎片),於是就有了記憶體池的概念(記憶體池就是系統實現給開闢出一大塊空間等待使用,當需要空間的時候直接從記憶體池中取,當記憶體池中的記憶體也不夠使用時,再去Heap中開闢新的空間註入到記憶體池當中)

下麵就比較重要了,SGI空間配置器採用了兩級配置器,分為第一級配置器和第二級配置器,第一級配置器就是拿malloc()實現的,第二級配置器採用了記憶體池的概念;

先來講第一級配置器,第一級配置器的實現就是用的malloc()(因為很重要所以多說幾遍),它會不斷地嘗試開闢記憶體,如果沒有記憶體可供開闢,就會嘗試釋放空間,然後再取嘗試開闢空間,第一級配置器比較重要的一點就是實現了類似C++中new-handler機制,用來處理記憶體不足的情況

記憶體池是使用鏈表結構實現的(個人感覺和哈希桶的方法類似),而不採用順序表,這樣就可以更好的解決記憶體碎片的問題了。

註意,這裡的freelists是鏈表!

註意!這裡之前寫的不太清楚,freelists是一個順序表,每一個單元下邊都連接這一個鏈表,當區塊被客端(client)使用就會像上圖一樣將區塊撥出去,然後改變指針指向下一個節點(就是採用頭刪)

每個鏈表節點所管理的區塊大小也是不一樣的,第一個節點管理8bytes,第二個16bytes。。。以此類推,最後一個節點管理128bytes,所以當超過128位元組第二級配置器無法處理,就只好調用第一級配置器(記憶體不足時也會調用第一級配置器,因為第一級配置器裡面有記憶體不足處理常式)

下麵給出鏈表節點的實現

1 union obj
2 {
3     union obj *free_list_link;
4     char client_data[1];//The client sees this;
5 };   

裡面的聯合體指針就是指向下一個節點的指針,那個char是指向實際記憶體塊的指針,採用聯合體可以減少記憶體的消耗,不必專門維護一個指向下一個節點的指針

當節點所指的記憶體塊是空閑塊時,obj被看做一個指針,指向下一個節點,當節點已經被分配了記憶體之後,被視為一個指針,指向實際區塊

當分配函數allocate()(alloc中申請記憶體的函數)發現沒有可用的區塊之後,就會去記憶體池中申請新的區塊(調用chunk_alloc()函數) ,預設申請20個區塊,當記憶體池的可用記憶體不足20個區塊,有多少給多少,如果連一個區塊的記憶體都不夠,就往記憶體池中註入記憶體(就是再去開闢一些放進記憶體池裡),就會去free_lists中遍歷,尋找記憶體池分配給自由鏈表但是卻處於空閑狀態的節點,將這些節點的存儲空間歸還個記憶體池,再遞歸去使用chunk_alloc()函數判斷是否空間夠分配;如果很不幸,還是不夠用,那麼註意!!會將記憶體池中剩餘的小空間分配成低位區塊分給自由鏈表(就是說假如需要申請16個位元組的節點區塊,不夠了,但是記憶體池中有8個位元組的空間,當然不能夠浪費咯,趕緊分配出去)然後去往記憶體池中註入記憶體(就是再去開闢一些放進記憶體池裡)。

這個是《STL源碼剖析》里的一個例子

當整個系統堆得記憶體都不夠了的時候,就chunk_malloc()就會四處尋找可用記憶體,嘗試釋放一些沒用的空間,如果還是無法找到就去調用第一級配置器,因為一級配置器里有記憶體不足處理常式


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HashMap 的性能因數 1. 容量:表示桶位的數量。 2. 初始容量: 表在創建是所擁有的桶位數。 如果你知道將要在HashMap存儲多少項,創建一個初始容量合適的HashMap將可以避免自動再散列的開銷 /** * The default initial capacity - MUST be ... ...
  • 說是解決,其實不是很完美的解決的,寫出來只是想記錄一下這個問題或者看一下有沒有哪位仁兄會的,能否知道一二。 下麵說說出現問題: 問題是這樣的,當我查詢一個一對多的實體的時候,工具直接就爆了,差不多我就猜到是哪裡死迴圈了,最後等了好久,查看原因,果然是堆溢出,再然後是jsckson的錯誤。那麼必然是序 ...
  • 最近加入了python部落,感覺裡面的刷題寶很有意思,玩了一下,知道了許多以前並不清楚的內置函數,然後感覺到快要記不住了,所以開始陳列一下 1.divmod(a,b):取a除以b的商和餘數,功效等價於(a//b, a%b); 2.dir():參數為函數名,類名。它會告訴我們對應函數包含有什麼參數 3 ...
  • 前兩天學習了兩種java操作excel的方法,對於網站需要創建、修改、導出excel文件,可以使用這兩種方法,第一種方法是使用JExcel,第二種方法是使用poi中的HSSF,前一種方法比較簡單。這裡做個總結。 1.JExcel,需要的jar包jxl.jar 只讀文件 Workbook wb=Wor ...
  • Spring 框架提供了構建 Web 應用程式的全功能 MVC 模塊。Spring MVC屬於SpringFrameWork的後續產品,已經融合在Spring Web Flow裡面。Spring MVC的易用性、功能強大等優點已經被越來越多的企業所接受,也成為一個使用廣泛的mvc框架。因此,尚學堂對 ...
  • 引言 本文是圍繞Linux udp api 構建一個簡易的多人聊天室.重點看思路,幫助我們加深 對udp開發中一些api瞭解.相對而言udp socket開發相比tcp socket開發註意的細節要少很多. 但是水也很深. 本文就當是一個demo整合幫助開發者回顧和繼續瞭解 linux udp開發的 ...
  • 同步工具類主要包括閉鎖(如CountDownLatch),柵欄(如CyclicBarrier),信號量(如Semaphore)和阻塞隊列(如LinkedBlockingQueue)等; 使用同步工具類可以協調線程的控制流; 同步工具類封裝了一些狀態,這些狀態決定線程是繼續執行還是等待,此外同步工具類 ...
  • 在Qt中,給主視窗(QMainWindow類)添加工具欄非常方便,直接使用addToolBar 即可,如下所示: 但是,addToolBar 是QMainWindow 類的函數,在QWidget類中沒有addToolBar類似的添加工具欄的函數,所以無法直接給QWidget類(QWidget的子類) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...