我在C++11 STL中阅读了很多关于内存管理的帖子,但是我并没有找到一个令人满意的答案。
我的情况:我开发了一个长时间运行的服务器,它在4-6周内运行。目前,我使用了大量位于堆栈上的旧C代码char [x][y]或char [z]变量。
我怀疑STL内存管理是否仍然可靠,在运行数周的程序中广泛使用它,并在t̲h̲i̲的̲周期中服务于1 000多万个线程,每个线程都有大量的STL操作。
更具体地说:我希望将堆栈中的所有固定大小的变量重写为std::vector<std::string>或std::string类型。
我的问题:
编译器是gcc 4.9.3
发布于 2016-07-02 14:05:39
首先,我非常感谢所有的评论和妮可的答复。他最后的评论,关于碎裂,击中了钉子的头。
1)碎片取决于这数百万线程到底在做什么的细节。
在深入分析了这个项目之后,我意识到有数百万内存分配和发布。
因此,我编写了自己的STL内存分配器,其中:
unordered_map来维护所有的指针。我的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字节的维护数据。E.q.分配1字节将导致一个实际大小为48字节的内存块。Max Used Pointers:这是所有正在运行的线程同时使用这个大小的内存块的数量。换句话说,这个内存Size * Max Used Pointers是从操作系统物理上分配的。Total Requested Count:每次请求分配对齐大小时,此计数都会增加。对我来说,这意味着我可以节省数百万的分配和发行版,而且我不知道使用默认的STL分配器,碎片会是什么样子。
2)我可以摆脱C风格的旧代码,可以使用更方便的STL容器。
3)演出情况良好。对我来说,这意味着我的分配器不是最快的,但考虑到它完全是多线程安全的,并且每秒处理数千个请求,它完全满足了我的需要。
所以,答案是,平心而论,我仍然不知道默认的STL内存分配器有多可靠,但由于我得到的这些事实--至少是,--这是内部情况的一个线索。
假设我的分配器是免费的,在运行了很长一段时间并为数百万个请求提供服务之后,我可以为我关闭这个案例。
发布于 2016-06-15 20:24:53
我能否完全安全地将我的程序重写到新的现代STL表示法,并摆脱旧的C代码?
首先,STL并不是新的;它可以追溯到C++本身标准化之前。其次,我们称它为C++标准库。
第三,只要您的线程遵循C++的要求(即:不要以C++不允许的方式终止),并且不会泄漏内存,那么是的,您会没事的。
在数百万个线程中长时间运行时,是否存在内存碎片?
您将从驻留在堆栈上的对象转到动态分配内存。当然,存在着内存碎片的可能性。
这与C++标准库容器完全无关。这是使用动态分配的结果。
同样重要的是,如果您想使用更好的、固定大小的堆栈数组,可以只使用std::array<char, ...>。同样,在很多情况下,使用小字符串优化的std::string实现提供了一个很好的折衷方案,如果字符串小于最大大小,就放弃分配内存。
那表演呢?使用旧的C代码,在堆栈上设置变量不会对性能产生任何影响。
它使堆栈更长,这给出了1000万个线程,可能会导致您提交更多的内存页。再说一次,也许不是。
无论如何,当涉及到超线程应用程序时,内存分配总是一个问题。从本质上说,内存分配必须是可重入的。这意味着互斥锁等等。
您可以设计分配和释放内存的原子方法,但这往往需要固定大小的分配。这样的事情往往有它们自己的缺点。您可以从其中分配线程本地内存池。所有这些都需要使用您自己的内存分配器。
但最重要的是。这些问题与具体使用C++标准库类型无关。这只是从静态内存到动态分配时发生的事情。无论是使用malloc/free还是标准库容器,问题都在于动态分配。
https://stackoverflow.com/questions/37844940
复制相似问题