2

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

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

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

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

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

4

2 回答 2

0

我浏览了 Linux 源代码,发现了这个

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

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

编辑:它是在这个提交中添加的

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

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

于 2019-01-21T10:20:25.663 回答
0

mallocandfree调用不仅仅是简单的包装器和sbrk系统mmap调用。这使得返回的东西与对andgetrusage的调用不符。这些函数的任何重要实现都将在进程本身内部管理一个空闲列表,然后再考虑将任何内容返回给系统。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()将从程序的角度返回分配的字节数。它考虑了各种分配技术,例如sbrkand mmap,并将舍入和开销视为malloc()(and new) 的分配内存的一部分。

使用 OSX 时,事情就不那么光明了。您可以查看苹果的 malloc() 的源代码,特别是 at 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 上不走运,除非有人可以纠正我。

于 2019-01-21T12:51:11.573 回答