当前位置: 首页 > 知识库问答 >
问题:

内存分配和进程内存使用

宗冷勋
2023-03-14

我想了解为什么多次动态分配调用的数据比直接在代码中指定的或通过malloc的单个调用分配的数据使用如此多的内存。

例如,我用C编写了以下两个代码:

测试1.c:int x用malloc分配

int main (void)
{
    int *x;
    int i, n=1048576; //n=1024*1024;

    printf("size = %lu\n", n* sizeof(int));

    for(i=0; i<n; i++)
    {
        x = malloc(sizeof(int));
        *x=i;
    }
    printf("Look at top and then press something to finish.");fflush(stdout);
    getc(stdin);
    return 0;
}

我在这里没有使用free来保持简单。当程序等待交互时,我查看另一个终端中的顶级功能,它向我显示了以下内容:

PID  USER   PR  NI  VIRT   RES    SHR  S  %CPU %MEM  TIME+   COMMAND                                    
1384 root   20  0   41300  34076  1300 S  0.0  3.3   0:00.47 test1

test2. c: int x不是动态分配的

int main (void)
{
    int x[1048576]; //x[1024*1024]
    int i, n=1048576;

    printf("size = %lu\n", n* sizeof(int));

    for(i=0; i<n; i++)
    {
        x[i]=i;
    }
    printf("Look at top and then press something to finish.");fflush(stdout);
    getc(stdin);
    return 0;
}

顶部显示:

PID  USER   PR  NI  VIRT    RES    SHR  S  %CPU %MEM  TIME+   COMMAND                                    
1352 root   20  0   12404   5500   1304 S  0.0  0.5   0:00.05 test2 

我还编写了第三个代码,其结果与test2相同,我在test2中使用了:

x = malloc(n*sizeof(int));
for(i=0; i<n; i++)
    {
        x[i]=i;
    }

为什么进程的内存使用有这么大的差异?那是因为malloc请求新的内存页并且有内存被浪费吗?还是malloc分配了更多的内存?

test1使用总内存的3.3%,test2使用0.5%。

我正在docker内的Centos 5 64位上执行这些测试。

虚拟环境中的内存:

$ free -m
              total        used        free      shared  buff/cache   available
Mem:            995          98         845           3          51         808
Swap:          1162         194         967

共有2个答案

岳枫
2023-03-14

每次用户请求一些内存时,系统都需要进行一些整理。当仅用指针调用free就足以让系统取消其内存分配时,应该记住这一点。

因此,在您的第一个示例中,您请求内存n次,而在第二个示例中只请求一次。您打算使用的内存是相同的,但系统必须“记住”的信息不是。

隗轶
2023-03-14

必须跟踪每个内存分配,以便free()可以释放空间以供重用。实际上,这意味着分配的内存大小是最小的;对于32位程序,它可以是8或16字节,对于64位程序,它可以是16-32字节(这取决于系统和使用的C库版本)。

当您单独分配一百万个整数时,每个整数使用8-32个字节,因此您实际上使用了8-32 MiB的内存。当您在堆栈上的单个数组中分配一百万个整数时,您使用的是4 MiB的内存。

因此,您会发现流程大小有很大差异。

当然,第一个程序会泄漏几乎所有的内存,但这与您提出的问题无关。

 类似资料:
  • 我在理解JVM进程如何分配自己的内存方面有一点差距。据我所知 其中堆外由线程堆栈、直接缓冲区、映射文件(库和JAR)和JVM代码本身组成; 目前,我正在尝试分析我的Java应用程序(Spring Boot Infinispan),RSS779M(它在docker容器中运行,所以pid 1是可以的): 换句话说,我想解释799M-(374M 89M)=316M堆外内存。 这些线程中的每一个都消耗1M

  • 我使用5.6.21-70.0进行性能测试。 当我跑步时 mysqlslp-a--并发=40--查询次数1000次--迭代=500次--引擎=innodb--debug-info-utest-p 做一些性能测试,ram增长超过最大内存使用量,永不释放 当完成mysqlslap时,内存显示使用78% 我有1G物理内存,不使用交换 KiB Mem:总共1016656个,使用953808个,免费62848

  • 我开发了kervel驱动程序,并与dell进行了通信。尝试做一个快照功能和行走功能 我的结构是 在我的快照函数中,我这样做。 在walk函数中,我执行以下操作 当我在我的驱动程序条目中(当驱动程序加载时)使用这个函数时,所有的工作都很好。但当我从dll中调用它时,只有2秒钟的时间“Word Fine”,然后我就会出现蓝屏。 当我尝试从SM_MSI结构中删除Name变量时,所有工作都很完美。!!所以

  • 问题内容: 这是一篇受此评论启发的帖子,内容涉及如何在CPython中为对象分配内存。最初,这是在创建列表并将其添加到for循环中_以_ 实现列表理解的上下文中。 所以这是我的问题: CPython中有多少个不同的分配器? 每个功能是什么? 什么时候被正式称为?(根据此评论中的内容,列表理解可能不会导致调用, python在启动时会为其分配多少内存? 是否有规则来控制哪些数据结构在此存储器上首先获

  • 我有一个一直在思考的问题。以这个特殊的类为例 假设我有一个B类,它拥有一个使用listOne读取详细信息的方法。要查看数组列表,我需要首先获取列表的大小,以便我的代码知道数组列表何时结束。有两种方法可以做到这一点,一种是 或者我也可以用 在内存和效率方面,哪种方法更好?此外,假设我正在递归地读取一个非常大的数组。为了简单起见,让我们假设递归读取此数组将导致堆栈溢出异常。在这种情况下,第一个方法在理

  • 问题内容: 使用以下Java选项启动Apache Tomcat(Atlassian Confluence)实例: 但是,我看到启动后,它很快就耗尽了虚拟服务器上可用的1GB内存中的大部分。 总消耗的内存(堆+ PermGen)是否不应该保持在使用- Xmx指定的值以下?这引起的问题之一是我无法使用关闭脚本关闭服务器,因为它试图生成具有256MB内存的JVM,该JVM因不可用而失败。 问题答案: T