【问题标题】:allocating ram shows double the ram usage in task manager分配 ram 在任务管理器中显示双倍的 ram 使用率
【发布时间】:2011-10-03 01:37:31
【问题描述】:

做一些分析(内存和速度)我被win7似乎分配的内存正好是我要求的两倍的事实所困扰......注意这是我第一次在win7上进行这样的主动分析,所以我真的不知道会发生什么。

我正在使用 win7(64 位)下的快速版 MSVC 在循环中分配精确数量的 RAM。该应用程序已编译并以 32 位运行。

我分配了 24 MB 的内存,任务管理器显示我的应用程序正在使用 48MB(在所有内存列下,包括已提交,因为我实际上是在新区域内进行内存复制)。当我再获得 24 个(现在应该是 48MB)时,我的应用会跳到 96 个,等等。

这些被分配为 1,000,000 个 24 字节结构。

我在网上搜索过,但没有找到与我的观察完全相符的东西。

有人知道吗?

如果这只是操作系统的诡计(或无能?),是否有任何工具可以让我了解进程的实际内存消耗? (当应用程序开始涌现时,很难找到泄漏;-)

[-----------已编辑,附加信息-----------]

注意(通过控制台标题栏中的路径)我在发布模式下构建(使用 MSVC 2010 的所有默认“空”项目设置),因此没有分配额外的“调试”内存(可以是在某些项目上相当广泛)。

这是一个简短、完整的 C 应用程序,用于说明该行为:

#include <stdio.h>
#include <assert.h>
#include <conio.h>
#include <stdlib.h>
typedef unsigned int u32;
typedef struct myStruct MYS;
struct myStruct {
    u32 type;
    union {
        u32 value; 
        char * str;
        void * data;
        MYS ** block;
        MYS * plug;
    };
    u32 state, msg,  count, index;
};
int main(int argc, char *argv[]){
    int i, j;
    MYS *ref;
    printf ("size of myStruct: %d\n\n", sizeof(MYS));
    for(i=0; i < 10; i ++){
        printf("allocating started...\n");
        for (j = 0; j < 1000000 ; j ++){
            ref = (MYS *) malloc(sizeof(MYS));
            assert(ref);
            memset(ref, 0, sizeof(MYS));
        }
        printf("   Done... Press 'enter' for Next Batch\n");
        _getch();
    }
    _getch();
    return 0;
}

还有一张图片显示了我的机器在一个循环后的内存。每隔一次运行,它就会增加约 48MB 而不是 24MB!

【问题讨论】:

  • 你能显示你分配内存的那一行吗?
  • 你确定这个结构真的是24字节吗?可能会有一些对齐来填充它。
  • 已编辑问题...我添加了一个完整的代码示例,其中包含额外的构建细节和一个循环后我的任务管理器的图片。希望这会有所帮助:-)
  • 也许操作系统会主动保留更多内存,因为它知道它会在其他迭代中这样做(可能由编译器暗示)?也许您泄漏内存的事实正在影响它?您是否尝试过让它运行所有 10 次迭代?
  • 查看 SysInternal 的 VMMap。可能会对程序的内存消耗有所了解。

标签: c windows-7 malloc


【解决方案1】:

这可能是由于填充、内部管理结构和内存对齐限制的组合。

当您调用malloc(size) 时,您实际上并没有获得size 字节的缓冲区。您会得到一个 至少size 字节的缓冲区。这是因为,出于效率原因,您的操作系统更喜欢仅处理几种不同大小的内存缓冲区,并且不会定制缓冲区以节省空间。例如,如果您在 Mac OS 上请求 24 字节,您将获得 32 字节的缓冲区(浪费了 25%)。

将您的操作系统用于管理malloced 缓冲区的结构添加到该分配开销(可能会占每个分配的几个额外字节),以及填充可能会增加对象大小的事实(到您的倍数编译器的首选对齐方式),您会发现将数百万个小对象分配到单独的缓冲区中非常昂贵。

长话短说:只分配一个sizeof (YourType) * 1000000 的大缓冲区,您应该不会看到任何明显的开销。分配一百万个sizeof (YourType) 对象,最终会浪费大量空间。

【讨论】:

  • 谢谢,所以我应该为这些结构实现自己的(内存高效)池分配器?我将处理数百万个这样的小结构。一次分配 n 个数字,然后在需要下一次分配之前密切关注它剩余的数量(反之亦然)。
  • 是的,如果您需要处理大量的小内存分配,您应该创建一个使用malloc 的分配器一次保留大块内存。
  • 顺便说一句,我做了很多测试,似乎我的 win7 机器上的所有 malloc 调用都增加了 20-30 字节(平均基于数百万不同大小的分配)。所以我猜系统的分配器本身就非常耗内存(对于任何给定的分配,它都有很多值跟踪)。
【解决方案2】:

malloc 不是 Windows 上的操作系统服务,它是由您的编译器实现的。如另一个答案所示,它可能有自己的分配策略,并且通常建立在 HeapAlloc 之上,它有自己的一些开销。

如果您想分配特定数量的页面,请致电VirtualAlloc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 2014-05-27
    • 2012-02-26
    • 1970-01-01
    相关资源
    最近更新 更多