繁体   English   中英

STL内存管理对于长期运行的程序是“可靠的”吗?

[英]Is STL memory management “reliable” for a long running program?

我在C ++ 11 STL中阅读了很多关于内存管理的帖子,但我找不到令人满意的答案。

我的情况:我开发了一个长期运行的服务器[它运行大约4-6周]。 目前我使用了很多位于堆栈上的 C代码char [x][y]char [z]变量。

怀疑 STL内存管理是否仍然可靠 ,在一个运行数周的程序中广泛使用它,并在此期间服务超过1000万个线程,每个线程将有很多STL操作。

更具体一点:我想将位于堆栈上的所有修复大小的变量重写为std::vector<std::string>std::string类型。

我的问题:

  1. 我可以完全安全地将我的程序重写为新的现代STL表示法并摆脱旧的C代码吗?
  2. 在数百万个线程中长时间运行时是否存在任何内存碎片
  3. 性能如何? 使用堆栈上具有变量的旧C代码不会对性能产生任何影响。

编译器是gcc 4.9.3

我可以完全安全地将我的程序重写为新的现代STL表示法并摆脱旧的C代码吗?

首先,STL不是新的; 它可以追溯到C ++本身标准化之前。 其次,我们称之为C ++标准库。

第三,只要你的线程遵循C ++的要求(即:不以C ++不允许的方式终止),并且你不泄漏内存,那么是的,你会没事的。

在数百万个线程中长时间运行时是否存在任何内存碎片?

你将从生活在堆栈上的对象转向动态分配内存。 当然存在内存碎片化的可能性。

这与C ++标准库容器完全无关。 这是使用动态分配的产物。

同样重要的是,如果要使用更好的固定大小的堆栈数组,可以使用std::array<char, ...> 然后,在很多情况下,使用小字符串优化的std::string实现提供了相当好的折衷,如果字符串低于某个最大大小,则放弃分配内存。

性能如何? 使用堆栈上具有变量的旧C代码不会对性能产生任何影响。

它使你的堆栈更长,这给了1000万个线程,可能会导致你提交更多页面的内存。 然后,也许不是。

无论如何,当涉及到超线程应用程序时,内存分配总是一个问题。 内存分配本质上必须是可重入的。 这意味着互斥锁定等等。

您可以设计分配和释放内存的原子方法,但这往往需要分配固定大小。 而这些事情往往有其自身的缺点。 您可以拥有从中分配的线程本地内存池。 所有这些都需要使用自己的内存分配器。

但最重要的是......这些问题再次无关使用C ++标准库类型具体 这就是从静态内存到动态分配时会发生的情况。 无论您使用的是malloc/free还是标准库容器,问题都在于动态分配。

首先,我非常感谢所有评论和Nicol的回答。 关于碎片化的他的最后一条评论在头上打了一针。

1)破碎取决于正是这些数以百万计的线程正在做的事情的细节。

在深入分析了项目后,我意识到有数百万个内存分配和发布。

因此我编写了自己的STL Memory Allocator:

  1. 有一个内部unordered_map来维护所有指针。
  2. 是多线程安全的。
  3. 根据第1点,它重用了被标记为空闲的释放指针。
  4. 卸载 Controller,请求的内存大小[通过STL]与16字节大小对齐。

我的STL内存分配器记录所有请求,这是摘要[摘要]:

Statistics:
     Total allocated Memory: 813'041'344 bytes
     Administrative Memory : 3'464'152 bytes
     Available pointers    : 2'500
+-------------------------------------------------------------------------+
| Index | Aligned Memory Size | Max Used Pointers | Total Requested Count |
+-------------------------------------------------------------------------+
|      1|                   48|                296|             49'545'399|
|      2|                   64|                469|             73'226'993|
|      3|                   80|              1'167|             67'108'769|
|      4|                   96|                129|             12'864'168|
|      5|                  112|                281|              4'528'422|
|      6|                  128|                 64|              8'715'454|
|      7|                  144|                 74|              5'148'202|
|     10|                  192|                387|              1'313'920|
|     11|                  208|                 26|              1'311'779|
|     13|                  272|                 56|             11'574'551|
|     15|                  352|                368|              1'178'994|
|     18|                  512|                262|              3'224'044|
|     22|                  656|                  5|              2'586'081|        
+-------------------------------------------------------------------------+

传说:

  • Aligned Memory Size :每个请求的块对齐到16字节+ 32字节的维护数据。 Eq分配1个字节导致实际48字节大小的存储器块。
  • Max Used Pointers :这是所有正在运行的线程同时使用此大小的内存块的数量。 换句话说,该存储器[ Size * Max Used Pointers ]是从OS物理分配的。
  • Total Requested Count :每次Total Requested Count [对齐大小]分配时,此计数都会增加。

对我来说,这意味着我可以保存数百万的分配和发布,我不知道碎片在默认的STL分配器上会是什么样子。


2)我可以摆脱旧的C风格代码,我可以使用更方便的STL容器。


3)表现还可以 对我而言,这意味着我的分配器不是最快的,但考虑到它完全是多线程安全的,并且每秒服务数千个请求,它完全满足我的需求。


所以,答案是,[公平]我仍然不知道默认的STL内存分配器有多可靠,但由于我所提到的事实 - 至少 - 一个线索内部发生的事情。

假设我的分配器没有错误[我可以期待长时间运行并提供数百万个请求]我可以为我关闭此案例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM