如何在Linux(和OSX)上查询已分配的内存量?

马丁·比森(Martin Bisson)

尽管这看起来可能是其他问题的重复,但让我解释一下为什么不是这样。

我希望在达到特定内存限制时,使应用程序的特定部分正常降级。我本可以根据剩余的可用物理内存来使用标准,但这并不安全,因为操作系统可以在达到标准之前开始调出我的应用程序使用的内存,这会认为还剩下一些物理内存,并保持出于同样的原因,我无法使用该进程当前使用的物理内存量,因为一旦OS开始换出我,我将继续分配为OS页面内存,因此该数量不再增长。

因此,我根据应用程序分配的内存量(即非常接近虚拟内存大小)选择了一个标准。

这个问题(如何从进程内部确定CPU和内存消耗?)提供了查询当前进程使用的虚拟内存量的好方法,我正是我所需要的。

在Windows上,我正在使用GetProcessMemoryInfo()PrivateUsage字段,效果很好。

在Linux上,我尝试了几种无效的方法(下面列出)。虚拟内存使用对我不起作用的原因是由于在Linux上的NVidia硬件上创建OpenCL上下文时发生了某些事情。驱动程序保留虚拟内存空间的区域,足以容纳所有RAM,所有交换和所有视频内存。我的猜测是对统一地址空间和所有内容都这样做。但这也意味着该进程报告使用了大量内存。例如,在我的系统上,top将在VIRT列中报告23.3 Gb(12 Gb的RAM,6 Gb的交换,2 Gb的视频内存,这为NVidia驱动程序保留了20 Gb)。

在OSX上,通过使用task_info()virtual_size字段,我得到的数字也比预期的大(对于在Windows上甚至不接近1 Gb的应用程序,该数字为几Gb),但不如Linux大。

所以这是一个大问题:如何获得应用程序分配的内存量?我知道这是一个模糊的问题(“分配的内存”是什么意思?),但是我很灵活:

  • 我希望包括应用程序的静态数据,代码段以及所有内容,但是我可以不用。
  • 我宁愿包括分配给堆栈的内存,但我可以不用。
  • 我希望包括共享库使用的内存,但是我可以不用。
  • 我真的不在乎mmap的东西,在那时无论有无,我都可以做到。
  • 等等。

真正重要的是,该数目随着动态分配(新分配,malloc分配)而增长,并在释放内存时减小(我知道这可能与实现有关)。

我尝试过的事情

这是我尝试和/或考虑过的几种解决方案,但对我而言不起作用。

  1. 从/ proc / self / status中读取

    这是如何从进程内部确定cpu和内存消耗的方法。但是,如上所述,这将返回虚拟内存量,这对我不起作用。

  2. 从/ proc / self / statm中读取

    非常轻微最坏:根据http://kernelnewbies.kernelnewbies.narkive.com/iG9xCmwB/proc-pid-statm-doesnt-match-with-status,这是指Linux内核代码,这两个值之间的唯一区别是第二个不减去reserved_vm虚拟内存量。我本来reserved_vm希望包含OpenCL驱动程序保留的内存,但事实并非如此。

  3. 用途mallinfo()uordblks领域

    这似乎并不包括所有分配(我猜是news缺失了),因为虚拟内存空间增长了+ 2Gb(在完成了一些繁重的工作之后仍然保留了内存),我只看到了mallinfo()返回的数字大约增加0.1Gb

  4. 从/ proc / self / smaps读取[heap]节的大小

    对于将虚拟内存空间增加+ 2Gb的工作,此值开始于336,760 Kb左右,最高达到1,019,496 Kb,然后再也没有下降,因此我不确定我是否真的不能依靠这个数字...

  5. 监视我的应用程序中的所有内存分配

    是的,在理想的世界中,我可以控制分配内存的每个人。但是,这是一个遗留应用程序,使用了大量不同的分配器,一些malloc,某些new,某些特定于操作系统的例程等。有些插件可以执行任何所需的工作,可以使用不同的编译器进行编译,因此,尽管这对于真正控制内存非常有用,但这在我的上下文中不起作用。

  6. 在OpenCL上下文初始化之前和之后读取虚拟内存大小

    尽管这可能是解决问题的一种“ hacky”方法(而且我可能不得不退后),但我真的希望有一种更可靠的查询内存的方法,因为OpenCL上下文可以在我无法控制的地方初始化,并且其他类似但非OpenCL的特定问题可能会蔓延,而我对此一无所知。

所以这就是我所拥有的。我还没有尝试过另一件事,因为它只能在OSX上运行,但是要使用“为什么mstats和malloc_zone_statistics释放后不显示已恢复的内存”中描述的方法,即使用malloc_get_all_zones()malloc_zone_statistics(),但我认为这可能是与相同的问题mallinfo(),即未将所有分配都考虑在内。

因此,有人可以建议一种查询Linux中给定进程(以及OSX的内存使用情况,即使这是一种不同的方法)的方式的查询方法(这个术语含糊不清,请参见上文以获取准确性)?

马丁·比森(Martin Bisson)

这是我最终使用的内容。我扫描/ proc / self / maps并求和满足我的条件的所有地址范围的大小,即:

  • 仅包括inode 0的范围(即,没有设备,没有映射的文件等)
  • 仅包含至少一个可读,可写或可执行的范围
  • 只包含私人记忆
    • 在我的实验中,我没有看到inode 0的共享内存实例。也许是进程间共享内存...?

这是我的解决方案的代码:

size_t getValue()
{
    FILE* file = fopen("/proc/self/maps", "r");
    if (!file)
    {
        assert(0);
        return 0;
    }

    size_t value = 0;

    char line[1024];
    while (fgets(line, 1024, file) != NULL)
    {
        ptrdiff_t start_address, end_address;
        char perms[4];
        ptrdiff_t offset;
        int dev_major, dev_minor;
        unsigned long int inode;
        const int nb_scanned = sscanf(
            line, "%16tx-%16tx %c%c%c%c %16tx %02x:%02x %lu",
            &start_address, &end_address,
            &perms[0], &perms[1], &perms[2], &perms[3],
            &offset, &dev_major, &dev_minor, &inode
            );
        if (10 != nb_scanned)
        {
            assert(0);
            continue;
        }

        if ((inode == 0) &&
            (perms[0] != '-' || perms[1] != '-' || perms[2] != '-') &&
            (perms[3] == 'p'))
        {
            assert(dev_major == 0);
            assert(dev_minor == 0);
            value += (end_address - start_address);
        }
    }

    fclose(file);

    return value;
}

由于这是遍历/ proc / self / maps中的所有行,因此以这种方式查询内存比使用如何从进程内部确定CPU和内存消耗中的“当前进程当前使用的虚拟内存”慢得多

但是,它提供的答案更接近我的需求。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在OSX上检查内存映射

来自分类Dev

如何在解析过程中减少内存量

来自分类Dev

如何在C ++中释放已分配的内存?

来自分类Dev

如何在Linux上监视内存IO

来自分类Dev

跟踪Linux上的内存分配

来自分类Dev

如何在OSX上获得较高的内存使用率

来自分类Dev

如何在我指向的地址上动态分配内存?

来自分类Dev

如何在.NET Core中分配连续和固定内存

来自分类Dev

如何从iPython界面找出pyspark的内存量?

来自分类Dev

如何衡量堆栈消耗的内存量?

来自分类Dev

如何增加 Corda 节点可用的内存量?

来自分类Dev

有没有办法查询重新分配的作用,或者阻止它复制Windows和Linux上的所有内存?

来自分类Dev

Linux内核引导:当DTB和initramfs最初位于内存中时,如何完成内存分配?

来自分类Dev

确定一行代码中分配的内存量

来自分类Dev

使用分配会减少使用的内存量吗?

来自分类Dev

Iterator :: collect是否分配与String :: with_capacity相同的内存量?

来自分类Dev

使用分配会减少使用的内存量吗?

来自分类Dev

确定一行代码中分配的内存量

来自分类Dev

如何在Linux上的Common Lisp中内存映射文件?

来自分类Dev

如何在Linux内核上启用内存区域回收模式?

来自分类Dev

如何在Linux上找到已卸载分区的大小?

来自分类Dev

声明多个结构并将其覆盖在已分配的内存上

来自分类Dev

在任务管理器上看到已分配的内存

来自分类Dev

如何在 Linux 上测量 CPU 使用率和内存百分比与时间的关系?

来自分类Dev

检查如何在Linux系统上分配空间

来自分类Dev

如何在64-linux上的c ++中使用new运算符动态分配大内存(如10 G)?

来自分类Dev

如何在OSX上迭代所有已挂载的文件系统

来自分类Dev

测量外部程序使用的时间,内存量和cpu

来自分类Dev

以编程方式确定Spark可用的内核数量和内存量

Related 相关文章

  1. 1

    如何在OSX上检查内存映射

  2. 2

    如何在解析过程中减少内存量

  3. 3

    如何在C ++中释放已分配的内存?

  4. 4

    如何在Linux上监视内存IO

  5. 5

    跟踪Linux上的内存分配

  6. 6

    如何在OSX上获得较高的内存使用率

  7. 7

    如何在我指向的地址上动态分配内存?

  8. 8

    如何在.NET Core中分配连续和固定内存

  9. 9

    如何从iPython界面找出pyspark的内存量?

  10. 10

    如何衡量堆栈消耗的内存量?

  11. 11

    如何增加 Corda 节点可用的内存量?

  12. 12

    有没有办法查询重新分配的作用,或者阻止它复制Windows和Linux上的所有内存?

  13. 13

    Linux内核引导:当DTB和initramfs最初位于内存中时,如何完成内存分配?

  14. 14

    确定一行代码中分配的内存量

  15. 15

    使用分配会减少使用的内存量吗?

  16. 16

    Iterator :: collect是否分配与String :: with_capacity相同的内存量?

  17. 17

    使用分配会减少使用的内存量吗?

  18. 18

    确定一行代码中分配的内存量

  19. 19

    如何在Linux上的Common Lisp中内存映射文件?

  20. 20

    如何在Linux内核上启用内存区域回收模式?

  21. 21

    如何在Linux上找到已卸载分区的大小?

  22. 22

    声明多个结构并将其覆盖在已分配的内存上

  23. 23

    在任务管理器上看到已分配的内存

  24. 24

    如何在 Linux 上测量 CPU 使用率和内存百分比与时间的关系?

  25. 25

    检查如何在Linux系统上分配空间

  26. 26

    如何在64-linux上的c ++中使用new运算符动态分配大内存(如10 G)?

  27. 27

    如何在OSX上迭代所有已挂载的文件系统

  28. 28

    测量外部程序使用的时间,内存量和cpu

  29. 29

    以编程方式确定Spark可用的内核数量和内存量

热门标签

归档