2017-10-13 113 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的,这是多年的事实上的内存管理算法,我认为每个程序员都应该阅读。相反,创建容器时,在编译期间会知道许多因素,甚至可以在运行时预测更多因素,例如,我们知道要容纳的对象的大小。 利用这些知识,标准容器被编写成可以与通用分配器一起使用。

相关问题