2017-10-13 112 views
2

我讀過重複調用malloc/free可能會很昂貴,因此C++標準庫容器使用內存池而不是在它們的析構函數中調用free。另外,我讀過,這意味着C++標準庫容器的性能可能比手動分配和釋放所有必需的C風格數組要高。爲什麼C++標準庫容器使用內存池,如果顯然malloc/free對執行相同的工作?

不過,我很困惑這個,因爲現在我在C FAQ正在閱讀:(http://c-faq.com/malloc/freetoOS.html

大部分的malloc實現/免費不釋放的內存返回操作系統,但只是在相同的程序中將其用於將來的malloc調用。

這意味着,基本上malloc/free功能嘗試做同樣的工作作爲C++標準庫中的容器:他們嘗試優化重複聲稱/通過保持存儲池中回收內存,然後給節目片這個游泳池的要求。儘管如果執行一次,我可以看到這種優化的好處,但我的直覺告訴我,如果我們同時在幾個不同的抽象層上開始這樣做,性能可能實際上會下降 - 因爲我們將複製相同的工作。

我在這裏誤解了什麼?

+0

您在這裏誤解的是,除非您的工作涉及編寫C++庫本身,否則這應該不受任何人的擔憂。我永遠不會記得,在20多年的黑客C++中,這是我真正關心的事情。 –

+1

@SamVarshavchik這仍然不妨礙我出於普通的好奇心或學習問題而提出有關「爲什麼以這種方式構建而不是以這種方式構建」的問題。 – gaazkam

回答

1

標準庫的一些實現使用內存池。

一般來說,當您知道特定容器的內存需求時,您可能會比不知道容器特定需求的通用內存管理器更好地管理其內存。

例如,如果你使用std::list<int>列表中的每個節點具有相同的大小,並且具有容器保持未使用的節點列表(只有兩個指針賦值來添加或從自由列表中刪除到/節點)可能比釋放未使用的節點回到新/刪除(malloc/free)所使用的更通用但更復雜的通用內存管理器更快。

0

稱爲malloc的通用內存管理實用程序通常針對常見情況進行了優化。 由於系統應該支持多個進程,每個進程的行爲都不相同,所以這種優化對於某些應用程序來說可能非常好,而對其他應用程序來說則不是那麼好。 通用分配器會嘗試考慮以下通用準則:

  • 最大化的兼容性:一個分配器應該是插件兼容與他人;特別是它應該遵守ANSI/POSIX約定。
  • 最大化可移植性:依賴儘可能少的與系統相關的功能(例如系統調用),同時仍然爲僅在某些系統上發現的其他有用功能提供可選支持;符合對齊和尋址規則的所有已知系統約束。最小化空間:分配器不應該浪費空間:它應該從系統獲得儘可能少的內存,並且應該儘可能地減少碎片的存儲方式 - 在未使用的連續的內存塊中「漏洞」由程序。
  • 最小化時間:在平均情況下,malloc(),free()和realloc例程應儘可能快。
  • 使調諧能力最大化:可選功能和行爲應該由用戶靜態(通過#define等)或動態(通過諸如mallopt之類的控制命令)進行控制。
  • 最大化局部性:分配通常一起使用在一起的大塊內存。這有助於在程序執行期間最大限度地減少頁面和緩存缺失。
  • 最大化錯誤檢測:通用分配器似乎也不可能用作通用存儲器錯誤測試工具,例如Purify。但是,分配器應該提供一些手段來檢測由於覆蓋內存,多個空閒等而造成的腐敗。
  • 最大限度地減少異常

這個片斷是從一個偉大的document written by Doug Lea採取什麼叫Doug Lea的malloc的,這是多年的事實上的內存管理算法,我認爲每個程序員都應該閱讀。相反,創建容器時,在編譯期間會知道許多因素,甚至可以在運行時預測更多因素,例如,我們知道要容納的對象的大小。 利用這些知識,標準容器被編寫成可以與通用分配器一起使用。

相關問題