【问题标题】:Measure the maximum memory usage during a function call测量函数调用期间的最大内存使用量
【发布时间】:2019-06-14 16:53:44
【问题描述】:

我有一个 Linux/Mac C++ 库,它以函数调用的形式执行一系列步骤。我想测量每个步骤中的最大内存使用量。

对临时解决方案感兴趣,例如启动另一个轮询内存使用情况的线程、运行分析器等。

到目前为止,我发现 getrusage() 存在于 Mac 和 Linux 上,并且确实返回了最大内存使用量,但似乎无法在每次函数调用后重置此最大值。

有没有办法绕过这个限制?

编辑: 明确地说,我不想征用 malloc()/free() 并记录所有内容。我想要一个适合继续运行生产代码的解决方案。

【问题讨论】:

  • 那是关于在我的程序中添加分析器,我说过我不想这样做。
  • 为什么要添加?第二个是预加载的预编译包。
  • 在链接的问题中添加了 heaptrack。
  • 这是一个将分发给其他人的库。我不想在他们身上强制使用像gperftools 这样的分析器。它不是为在生产环境中运行而设计的——仅用于调试。

标签: c++ linux macos getrusage


【解决方案1】:

mallocfree 调用不仅仅是对 sbrkmmap 系统调用的简单包装。这使得getrusage 返回的内容与对mallocfree 的调用不一致。这些函数的任何重要实现都将在进程本身内部管理一个空闲列表,然后再考虑将任何内容返回给系统。

程序调用free(或delete),内存不会立即返回给操作系统(可能永远不会)。 free-ed 内存可以被任务重用,如果它调用malloc,但不能被其他进程重用。这使得getrusage 从操作系统的角度来看是正确的,但从程序的角度来看是不正确的。

在 Linux 上,您可以使用 mallinfo()

#include <malloc.h>
#include <cinttypes>
std::size_t memsize()
{
    auto data = mallinfo();
    return data.arena - data.fordblks + data.hblkhd;
}

这里,memsize() 将返回从程序的角度分配的字节数。它考虑了各种分配技术,例如sbrkmmap,并将舍入和开销作为malloc()(和new)分配内存的一部分。

在 OSX 中,事情就不那么光明了。您可以查看source code of apple's malloc(),特别是mstats,评论中指出:

/*
 * A Glibc-like mstats() interface.
 *
 * Note that this interface really isn't very good, as it doesn't understand
 * that we may have multiple allocators running at once.  We just massage
 * the result from malloc_zone_statistics in any case.
 */

这看起来不太有希望,并且:

#include <malloc/malloc.h>
#include <cinttypes>
std::size_t memsize()
{
    auto data = mstats();
    return data.bytes_used;
}

根据我的实验,看起来不太好。但这可能总比没有好,或者只是依靠getrusage。我认为你在 OSX 上不走运,除非有人能纠正我。

【讨论】:

  • 这完全是为了获取当前内存使用情况吗?我想要 peak 用法。不过有用的信息。
  • 你可以知道! Linux 和 Mac 都记录了这些信息(以 RSS 的形式,这对我来说很好)。此外,malloc_info() 返回一个 maximum 字段,这可能是我想要的,但它完全没有记录,所以我还不确定。
  • 我不知道您所说的“getrusage 似乎是一个近似值”是什么意思。我很确定不是。
  • @Timmmm 忘了我写的东西,一个错误
【解决方案2】:

我浏览了Linux源代码,发现this

        /*
         * Writing 5 to /proc/pid/clear_refs resets the peak
         * resident set size to this mm's current rss value.
         */

我还没有尝试过,但看起来很有希望。

编辑:它是在this commit中添加的

编辑 2:我查看了 MacOS 内核源代码 - 对应的值存储在 resident_max 中。不幸的是,似乎没有重置它的功能。

编辑 3:在 Linux 上,您可以使用 malloc_info() 获得最大分配的内存,但似乎没有办法重置它。它还依赖于您使用glibc

【讨论】:

    猜你喜欢
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多