了解 glibc malloc 修剪

2024-07-03

我目前正在开发的一些程序消耗的内存比我想象的要多得多。所以我试图了解 glibc malloc 修剪是如何工作的。我写了以下测试:

#include <malloc.h>
#include <unistd.h>

#define NUM_CHUNKS 1000000
#define CHUNCK_SIZE 100

int main()
{
    // disable fast bins
    mallopt(M_MXFAST, 0);

    void** array  = (void**)malloc(sizeof(void*) * NUM_CHUNKS);

    // allocating memory
    for(unsigned int i = 0; i < NUM_CHUNKS; i++)
    {
        array[i] = malloc(CHUNCK_SIZE);
    }

    // releasing memory ALMOST all memory
    for(unsigned int i = 0; i < NUM_CHUNKS - 1 ; i++)
    {
        free(array[i]);
    }

    // when enabled memory consumption reduces
    //int ret = malloc_trim(0);
    //printf("ret=%d\n", ret);

    malloc_stats();

    sleep(100000);
}

测试输出(不调用 malloc_trim):

Arena 0:
system bytes     =  112054272
in use bytes     =        112
Total (incl. mmap):
system bytes     =  120057856
in use bytes     =    8003696
max mmap regions =          1
max mmap bytes   =    8003584

尽管几乎所有内存都被释放,但此测试代码消耗的常驻内存比预期多得多:

[root@node0-b3]# ps aux | grep test
root     14662  1.8  0.4 129736 **118024** pts/10  S    20:19   0:00 ./test

处理smap:

0245e000-08f3b000 rw-p 00000000 00:00 0                                  [heap]
Size:             109428 kB
Rss:              109376 kB
Pss:              109376 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:    109376 kB
Referenced:       109376 kB
Anonymous:        109376 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
VmFlags: rd wr mr mw me ac 
7f1c60720000-7f1c60ec2000 rw-p 00000000 00:00 0 
Size:               7816 kB
Rss:                7816 kB
Pss:                7816 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:      7816 kB
Referenced:         7816 kB
Anonymous:          7816 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB

当我启用对 malloc_trim 的调用时,测试的输出几乎保持不变:

ret=1
Arena 0:
system bytes     =  112001024
in use bytes     =        112
Total (incl. mmap):
system bytes     =  120004608
in use bytes     =    8003696
max mmap regions =          1
max mmap bytes   =    8003584

然而,RSS 显着下降:

[root@node0-b3]# ps aux | grep test
root     15733  0.6  0.0 129688  **8804** pts/10   S    20:20   0:00 ./test

处理 smaps(在 malloc_trim 之后):

01698000-08168000 rw-p 00000000 00:00 0                                  [heap]
Size:             109376 kB
Rss:                   8 kB
Pss:                   8 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         8 kB
Referenced:            8 kB
Anonymous:             8 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB
VmFlags: rd wr mr mw me ac 
7f508122a000-7f50819cc000 rw-p 00000000 00:00 0 
Size:               7816 kB
Rss:                7816 kB
Pss:                7816 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:      7816 kB
Referenced:         7816 kB
Anonymous:          7816 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB
Locked:                0 kB

调用 malloc_trim 后,堆被收缩。我假设 8MB mmap 段仍然可用,因为最后一块内存尚未释放。

为什么 malloc 不自动执行堆修剪? 有没有一种方法可以配置 malloc,以便自动完成修剪(当它可以节省那么多内存时)?

我使用的是 glibc 版本 2.17。


很大程度上由于历史原因,小分配的内存来自由brk http://linux.die.net/man/2/brk系统调用。这是一个非常古老的系统调用——至少和版本 6 Unix https://en.wikipedia.org/wiki/Version_6_Unix——它唯一能做的就是改变尺寸一个在内存中的位置是固定的“竞技场”。这意味着,brk池不能缩小超过仍分配的块。

您的程序分配 N 块内存,然后释放其中的 N-1 块。它不会释放的一个块是位于highest地址。这是最坏的情况brk:即使 99.99% 的池未使用,大小也根本无法减小!如果您更改程序,使其未释放的块是array[0]代替array[NUM_CHUNKS-1],您应该看到 RSS 和地址空间在最终调用时都缩小了free.

当你明确调用malloc_trim,它尝试使用 Linux 扩展来解决此限制,madvise(MADV_DONTNEED) http://linux.die.net/man/2/madvise,它释放物理 RAM,但不释放地址空间(正如您所观察到的)。我不知道为什么这只发生在显式调用时malloc_trim.

顺便说一句,8MB mmap 段用于您的初始分配array.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解 glibc malloc 修剪 的相关文章

随机推荐

  • 错误:无法访问声纳服务器“http://localhost:9000”

    运行以下命令时 cmd c C sonar runner 2 4 bin sonar runner bat 声纳运行器安装在构建机器上 我收到以下错误 错误 声纳服务器 http 本地主机 9000 http localhost 9000
  • 库(传单)中的错误:没有名为“传单”的包

    我像这样编写了 docker 文件来部署闪亮的 r 应用程序 FROM rocker r base latest RUN apt get update apt get install y no install recommends sudo
  • Azure DevOps 仅限制组织内的访问

    我需要仅在组织网络内部限制对 Azure DevOps 的访问 怎么可能做到呢 我可以限制 IP 地址范围还是有其他方法 Azure DevOps 是一项云服务 因此您不能直接将其限制在您的 IP 地址范围内 但是有几个选项 1 Azure
  • 如何在 Perl 中呈现打开的文件夹选择对话框?

    如何在 Perl 中打开文件夹选择对话框 取决于您使用的 GUI 系统 也许还取决于平台 例如 在 Windows 上并使用Win32 GUI 您可以使用GetOpenFileName main is your main window my
  • 如何使用 Python 将 \t 写入文件

    我建立了一个网站 用户可以在表单中输入目录路径 我的程序将提取路径并写入一个文件 我的问题是 当路径包含一些特殊单词 例如 t n 时 程序无法正确写入文件 例如 C abc test 将变为 C abc TAB est 如何将字符串更改为
  • 使用自定义 Loader 时,不会在 ViewPager 片段上调用 ​​onResume()

    简洁版本 我有一个片段维护ViewPager为了显示另外两个片段 我们称它们为FragmentOne and FragmentTwo 启动应用程序时FragmentOne是可见的并且FragmentTwo位于屏幕外 仅当向左滑动视图时才可见
  • 如何在 wampserver 中安装 php 8?

    我正在尝试在 wampserver 中安装 PHP 8 并且按照 wampserver 官方论坛中的教程进行操作 但 PHP 8 不起作用 它显示以下错误 This PHP version 8 0 2 doesn t seem to be
  • 如何从一张图像平滑过渡到另一张图像

    我有一项活动正在更改图像视图定期 为此我编写了以下代码行 imageview setImageUri resId 我正在增加资源 ID 它工作正常 但突然从一张图像转换到另一张图像 我不希望这样 我希望图像视图平滑过渡到另一个图像 我怎样才
  • JQuery 隐藏对象

    好的 伙计们 我已经编辑了问题以便您能够理解 我有 10 张图片以及它们各自的名称 所以 你有 10 张图片和 10 个段落 由于图像不同 当然也有不同的名称 所以我不能使用类 因此 我对一张图像使用了一个 ID 对其名称使用了另一个 ID
  • 如何在 android 中创建带有网格视图的自定义警报对话框?

    我怎样才能创建一个警报对话框 with a GridView如上图所示 这是一个简单的实现 在活动内的代码中调用此方法 private void showAlertDialog Prepare grid view GridView grid
  • heroku 平台上的 Python 应用程序似乎在两个线程上启动

    有一个简单的Python应用程序部署在heroku平台上 from flask import Flask log APP STARTED single time connection to database and logging stuf
  • 该指南是随机的还是可猜测的

    我使用以下代码生成反 CSRF 令牌 TokenCSRF new Random Guid NewGuid GetHashCode Next 1 9999 ToString 这个令牌是可猜测的还是如预期的那样是真正随机的 编辑 我用以下内容替
  • 在 vb.net 中打乱字符串数组

    我正在 vb net 中开发一个网页 它将向用户生成许多多项选择题 我需要对已经放入数组中的四个答案进行洗牌 假设我必须遵循以下数组 array Correct Wrong1 Wrong2 Wrong3 我尝试使用以下方法 Public S
  • 如何让 IzPack 检查该软件的现有版本?

    我有一个我们使用的应用程序IzPack http izpack org创建安装程序 安装程序在当前状态下工作正常 但是 我需要添加功能以使其能够check是否是现有版本该软件已安装 我了解 IzPack 使用其开箱即用的方式支持此功能Che
  • 无法使用 smack、openfire 获取名册的存在

    我是 smack API 的新手 我正在尝试开发一个聊天应用程序 我试图在其中设置和获取状态 当我更改用户的存在时 它工作得很好 并且反映在 Openfire 服务器中 但是 当我尝试获取用户的存在状态时 即使他在 openfire 中的存
  • React-Native:警告:无法对未安装的组件执行 React 状态更新

    当我尝试从一个屏幕转换到另一个屏幕时 收到以下错误消息 这种情况发生在游戏应用程序中 其中多部手机参与游戏 并且根据它们在游戏中的角色以及该手机是主持游戏还是访客而具有不同的屏幕 当我尝试到达下一个屏幕 在左侧手机上 时 下图显示了此错误消
  • 如今,Macintosh 上的 TWAIN 状态如何?

    我目前正在开展一个项目 我们希望在 PC Windows 和 Macintosh 上与 TWAIN 扫描仪进行交互 在 Windows 上 我们基本上已经把一切都准备好了 并且代码可以在绝大多数扫描仪上成功运行 在 Mac OS X 上 我
  • 在执行 .toString() 后如何取回对象? [复制]

    这个问题在这里已经有答案了 我有一节课数据 java public class Data private String name private String age getters and setters for the above fi
  • 使用 gawk 解析 CSV 文件

    如何使用 gawk 解析 CSV 文件 简单设定FS 还不够 因为内部带有逗号的引用字段将被视为多个字段 使用示例FS 这不起作用 文件内容 one two three four five six seven eight nine 呆呆的脚
  • 了解 glibc malloc 修剪

    我目前正在开发的一些程序消耗的内存比我想象的要多得多 所以我试图了解 glibc malloc 修剪是如何工作的 我写了以下测试 include