Linux内存pipe理开销

我正在试图解释已经在Linux中使用我的应用程序的内存。 我做了一个基本的testing,发现如果我们新增了一些内存,它会为一个新内存分配至less32个字节。

这是我的代码。

#include <iostream> #include <stdlib.h> using namespace std; int main(int argc, const char** argv) { int iBlockSize = atoi(argv[1]); int iBlockCount = atoi(argv[2]); for (int i = 0 ; i < iBlockCount ; i++) { cout << (int*)(new char[iBlockSize]) << endl; } return 0; }; 

当我执行./a.out 8 100它给出了以下结果。

 .... .... .... 0xf6db10 0xf6db30 0xf6db50 0xf6db70 0xf6db90 0xf6dbb0 0xf6dbd0 0xf6dbf0 0xf6dc10 0xf6dc30 0xf6dc50 0xf6dc70 

我得到的所有记忆都有32个字节的差距。

直到24(BlockSize)是一样的。 如果超过24个字节,则为48个字节。

./a.out 25 100

 .... .... .... 0x18b30c0 0x18b30f0 0x18b3120 0x18b3150 0x18b3180 0x18b31b0 0x18b31e0 0x18b3210 0x18b3240 0x18b3270 0x18b32a0 

当我testing这个更大的尺寸; 发现我们得到的内存增加了16个字节的块,保持至less8字节的开销。

我的问题是,

  1. 我的testing是否正确?
  2. 这是linux内存pipe理的正确行为吗?
  3. 如果我们新增了8个字节,我们得到32个。其他24个是怎么回事? 重用或碎片开销?

C语言中的内存分配必须为所有原始类型返回适当对齐[0]的内存。 这意味着内存分配通常会给你至少8个字节对齐的内存,所以你可以在其中存储doubles

所以当你请求1字节的内存时,由于对齐的要求,你至少要使用8个字节。 在64位系统上,内存分配通常会给你16字节对齐的内存,因为这些系统通常有16字节大类型(SSE向量)

另外,内存分配器需要一些空间用于管理数据,比如分配的大小。 取决于实现,这个数据可以放在用户分配的内存块之前或之后。

[0]当地址/指针是访问的大小的倍数时,内存是对齐的,一些cpus不支持未对齐的访问(例如sparc),其他的(如x86)可能会有性能损失。

C ++ Standard的几行与主题相关; 我认为它简要地描述了这不是错误的行为。

在C ++程序中定义的任何分配和/或释放函数,包括库中的默认版本,都应符合3.7.4.1和3.7.4.2中规定的语义。 …

3.7.4.1分配函数 …返回的指针应适当对齐,以便它可以转换为任何完整对象类型的指针,其基本对齐要求(3.11)和…

3.11对齐对象对象类型具有对齐要求(3.9.1,3.9.2),该对齐要求限制了可以分配该类型对象的地址。 对齐是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。 …

我发现这篇文章

https://software.intel.com/en-us/articles/align-and-organize-data-for-better-performance

它说:“如果数据将通过向量指令加载和存储访问,请将数据对齐到16字节的边界。

所以看起来这是由glibc做出的对齐决定