我有一个用 C++ 编写的递归函数,它使用 new
动态分配二维数组.
如何测量函数在整个生命周期内在堆和堆栈上分配的空间总量?
这是一个如何测量堆栈的示例(这不是我的代码)。
unsigned int maxStackLocation ;
unsigned int minStackLocation ;
main ()
{
//get the address of a local variable before calling Quicksort
//the stack grows down, so this is the max stack location
int localVariable;
void *currPtrLocation = (void*)(&localVariable);
maxStackLocation = *(unsigned int *)(&currPtrLocation);
//we get the value for the minimum stack location in quicksort itself
//call quicksort
Quick (A, num);
space = maxStackLocation - minStackLocation;
}
//some redundant function whose stack usage will be measured
void Quick (unsigned int A[], int num)
{
if (num <= 1)
{
//check the stack usage
//figure out where we are on the stack by looking at the byte
// address of the local variable
//we do this by making a pointer to a local variable, and then
//casting it to a integer
void *currPtrLocation = (void*)(&num);
unsigned int currStackLocation = *(unsigned int*)(&currPtrLocation);
if (currStackLocation < minStackLocation)
minStackLocation = currStackLocation;
return;
}
}
编辑
Borgleader 指出我最初的问题“测量最大空间函数在整个生命周期内在堆和堆栈上分配”是不正确的。我已将“最大”更改为“总计”。
最佳答案
Valgrind 实际上可以为你做一个相当精确的测量。您只需要编写尽可能简单的示例来调用您的函数。
例如,一个程序只使用 for 循环和 main()
打印其参数(传递给 std::cout
函数)产生以下输出:
zaufi@gentop /work/tests $ valgrind --tool=drd --show-stack-usage=yes ./stack-usage-test-1
==26999== drd, a thread error detector
==26999== Copyright (C) 2006-2012, and GNU GPL'd, by Bart Van Assche.
==26999== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==26999== Command: ./stack-usage-test-1
==26999==
./stack-usage-test-1
==26999== thread 1 finished and used 11944 bytes out of 8388608 on its stack. Margin: 8376664 bytes.
==26999==
==26999== For counts of detected and suppressed errors, rerun with: -v
==26999== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
正如人们所见,唯一的线程将在堆栈上消耗近 12K。绝对大部分空间都被“浪费了”之前
main()
.为了进行更好的测量,有必要在单独的线程中运行目标函数。像这样:#include <iostream>
#include <thread>
int main(int argc, char* argv[])
{
auto thr = std::thread([](){std::cout << __PRETTY_FUNCTION__ << std::endl;});
thr.join();
return 0;
}
此代码将产生以下输出:
==27029== thread 2 finished and used 1840 bytes out of 8384512 on its stack. Margin: 8382672 bytes.
==27029== thread 1 finished and used 11992 bytes out of 8388608 on its stack. Margin: 8376616 bytes.
那肯定更好。所以测量一个什么都不做的函数,你得到了最小的堆栈使用量(在最后一个例子中它大约是 1840 字节)。因此,如果您要在单独的线程中调用目标函数,则必须从结果中减去 1840 字节(甚至更少)...
您可以使用以下简单算法自己完成几乎相同的操作:
pthread_attr_setstack()
(或 friend ))pthread_join()
之后成功,分析你的缓冲区找到一个区域,你之前分配的模式没有保留(甚至)在这种情况下,您最好对什么都不做的线程进行第一次测量——只是为了获得上述的最小使用大小。
关于c++ - 测量函数在整个生命周期内在堆和堆栈上分配的总空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13667187/