测量函数调用期间的最大内存使用量
Measure the maximum memory usage during a function call
我有一个 Linux/Mac C++ 库,它以函数调用的形式执行一系列步骤。我想测量每个步骤的最大内存使用量。
我不对临时解决方案感兴趣,例如启动另一个线程来轮询内存使用情况、运行 分析器等
到目前为止,我发现 getrusage()
出现在 Mac 和 Linux 上,并且 return 内存使用量达到最大,但是似乎无法重置每次函数调用后的最大值。
有什么办法可以绕过这个限制吗?
编辑: 明确地说,我不想征用 malloc()
/free()
并记录所有内容。我想要一个适合保留在 运行 生产代码中的解决方案。
我浏览了 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
.
malloc
和 free
调用不仅仅是 sbrk
和 mmap
系统调用的简单包装。这使得 getrusage
return 与对 malloc
和 free
的调用不一致。这些函数的任何重要实现都将在进程本身内部管理一个空闲列表,然后再考虑 return 向系统发送任何内容。
程序调用 free
(或 delete
),并且内存不会立即 returned 到操作系统(也许永远不会)。如果任务调用 malloc
,则 free
编辑的内存可以被任务重用,但不能被其他进程重用。这使得 getrusage
从 OS 的角度来看是正确的,但从程序的角度来看是不正确的。
在 Linux 你可以使用 mallinfo()
#include <malloc.h>
#include <cinttypes>
std::size_t memsize()
{
auto data = mallinfo();
return data.arena - data.fordblks + data.hblkhd;
}
这里,memsize()
将 return 从程序的角度分配的字节数。它考虑了各种分配技术,例如 sbrk
和 mmap
,并将舍入和开销视为 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 上运气不佳,除非有人可以纠正我。
我有一个 Linux/Mac C++ 库,它以函数调用的形式执行一系列步骤。我想测量每个步骤的最大内存使用量。
我不对临时解决方案感兴趣,例如启动另一个线程来轮询内存使用情况、运行 分析器等
到目前为止,我发现 getrusage()
出现在 Mac 和 Linux 上,并且 return 内存使用量达到最大,但是似乎无法重置每次函数调用后的最大值。
有什么办法可以绕过这个限制吗?
编辑: 明确地说,我不想征用 malloc()
/free()
并记录所有内容。我想要一个适合保留在 运行 生产代码中的解决方案。
我浏览了 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
.
malloc
和 free
调用不仅仅是 sbrk
和 mmap
系统调用的简单包装。这使得 getrusage
return 与对 malloc
和 free
的调用不一致。这些函数的任何重要实现都将在进程本身内部管理一个空闲列表,然后再考虑 return 向系统发送任何内容。
程序调用 free
(或 delete
),并且内存不会立即 returned 到操作系统(也许永远不会)。如果任务调用 malloc
,则 free
编辑的内存可以被任务重用,但不能被其他进程重用。这使得 getrusage
从 OS 的角度来看是正确的,但从程序的角度来看是不正确的。
在 Linux 你可以使用 mallinfo()
#include <malloc.h>
#include <cinttypes>
std::size_t memsize()
{
auto data = mallinfo();
return data.arena - data.fordblks + data.hblkhd;
}
这里,memsize()
将 return 从程序的角度分配的字节数。它考虑了各种分配技术,例如 sbrk
和 mmap
,并将舍入和开销视为 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 上运气不佳,除非有人可以纠正我。