10

在我的课堂上,我们有一项作业,其中一个问题是:

C 中的内存碎片:设计、实现和运行一个 C 程序,它执行以下操作:它为 3m 数组的序列分配内存,每个数组大小为 500000 个元素;然后它会释放所有偶数数组并分配一个由 m 个数组组成的序列,每个数组大小为 700000 个元素。测量程序分配第一个序列和第二个序列所需的时间量。选择 m 以耗尽程序可用的所有主内存。解释你的时间

我的实现如下:

#include <iostream>
#include <time.h>
#include <algorithm>

void main(){
    clock_t begin1, stop1, begin2, stop2;
    double tdif = 0, tdif2 = 0;
    for(int k=0;k<1000;k++){
    double dif, dif2;
    const int m = 50000;
    begin1 = clock();
    printf("Step One\n");
    int *container[3*m];
    for(int i=0;i<(3*m);i++)
    {
        int *tmpAry = (int *)malloc(500000*sizeof(int));
        container[i] = tmpAry;
    }
    stop1 = clock();
    printf("Step Two\n");
    for(int i=0;i<(3*m);i+=2)
    {
    free(container[i]);
    }
    begin2 = clock();
    printf("Step Three\n");
    int *container2[m];
    for(int i=0;i<m;i++)
    {
    int *tmpAry = (int *)malloc(700000*sizeof(int));
    container2[i] = tmpAry;
    }
    stop2 = clock();
    dif = (stop1 - begin1)/1000.00;
    dif2 = (stop2 - begin2)/1000.00;
    tdif+=dif;
    tdif/=2;
    tdif2+=dif2;
    tdif2/=2;
}
printf("To Allocate the first array it took: %.5f\n",tdif);
printf("To Allocate the second array it took: %.5f\n",tdif2);
system("pause");
};

我已经改变了几种不同的方式,但我看到的一致性是,当我最初为 3*m*500000 元素数组分配内存时,它会用完所有可用的主内存。但是当我告诉它释放它们时,内存不会释放回操作系统,所以当它分配 m*700000 元素数组时,它会在页面文件(交换内存)中执行它,因此它实际上不会显示内存碎片.

上面的代码运行了 1000 次并取平均值,这需要相当长的时间。第一个序列平均耗时 2.06913 秒,第二个序列耗时 0.67594 秒。对我来说,第二个序列应该需要更长的时间来展示碎片是如何工作的,但是由于使用了交换,这不会发生。有没有办法解决这个问题,还是我的假设错了?

我会在星期一向教授询问我有什么,但在此之前,任何帮助将不胜感激。

4

1 回答 1

2

许多 libc 实现(我认为包括 glibc)不会在您调用时将内存释放回操作系统free(),而是保留它以便您可以在没有系统调用的情况下在下一次分配时使用它。此外,由于现代分页和虚拟内存策略的复杂性,您永远无法确定任何东西在物理内存中的位置,这使得几乎不可能有意地对其进行碎片化(即使它是碎片化的)。您必须记住,所有虚拟内存和所有物理内存都是不同的野兽。

(以下是为 Linux 编写的,但可能适用于 Windows 和 OSX)

当您的程序进行第一次分配时,假设有足够的物理内存供操作系统挤入所有页面。它们在物理内存中并非彼此相邻——它们分散在任何可能的地方。然后操作系统修改页表以生成一组连续的虚拟地址,这些地址引用内存中分散的页面。但事情是这样的——因为你并没有真正使用你分配的第一个内存,它成为一个非常好的换出候选者。因此,当您来进行下一次分配时,内存不足的操作系统可能会换出其中的一些页面以为新页面腾出空间。因此,您实际上是在测量磁盘速度和操作系统分页机制的效率——而不是碎片。

请记住,一组连续的虚拟地址在实践中几乎从不物理上连续(甚至在内存中)。

于 2012-09-08T04:33:51.823 回答