测量 Linux 多线程应用程序的堆栈使用情况

Posted

技术标签:

【中文标题】测量 Linux 多线程应用程序的堆栈使用情况【英文标题】:Measuring stack usage for Linux multi-threaded app 【发布时间】:2010-09-08 16:28:59 【问题描述】:

我正在为 Linux 嵌入式平台开发一个多线程应用程序。

目前我正在将每个线程的堆栈大小(通过 pthread_set_attr)设置为一个相当大的默认值。我想将每个线程的值微调为更小的值,以减少我的应用程序的内存使用量。我可以通过反复试验将每个线程的堆栈大小设置为逐渐减小的值,直到程序崩溃,但应用程序使用大约 15 个线程,每个线程具有完全不同的功能/属性,因此这种方法非常耗时。

我更喜欢能够直接测量每个线程的堆栈使用情况。是否有一些实用人员可以推荐这样做? (例如,我来自 vxWorks 背景,使用 vxWorks shell 中的 'ti' 命令直接提供有关堆栈使用情况的统计信息以及有关任务状态的其他有用信息。)

谢谢

【问题讨论】:

【参考方案1】:

这里有两个工具可以测量 Linux 应用程序中(本机 pthread)堆栈的使用情况:

Valgrind Stackusage

Valgrind

用法:

valgrind --tool=drd --show-stack-usage=yes PROG

Valgrind 是一个稳定而强大的工具,不仅可用于测量堆栈使用情况。但它可能不支持所有嵌入式 CPU 型号。

堆栈使用

用法:

stackusage PROG

Stackusage 是一个轻量级工具,专为测量线程堆栈使用情况而设计,对于大多数配备 glibc 的嵌入式 Linux 平台来说应该是可移植的。在这一点上,它可能不像 Valgrind/drd 那样经过充分测试或成熟。

完全披露:我是 Stackusage 的作者。

【讨论】:

【参考方案2】:

我不知道有什么好的工具,但作为最后的手段,您可以在应用程序中包含一些代码来检查它,类似于以下内容:

__thread void* stack_start;
__thread long stack_max_size = 0L;

void check_stack_size() 
  // address of 'nowhere' approximates end of stack
  char nowhere;
  void* stack_end = (void*)&nowhere;
  // may want to double check stack grows downward on your platform
  long stack_size = (long)stack_start - (long)stack_end;
  // update max_stack_size for this thread
  if (stack_size > stack_max_size)
    stack_max_size = stack_size;

check_stack_size() 函数必须在一些嵌套最深的函数中调用。

然后作为线程中的最后一条语句,您可以将 stack_max_size 输出到某处。

stack_start 变量必须在线程开始时初始化:

void thread_proc() 
  char nowhere;
  stack_start = (void*)&nowhere;
  // do stuff including calls to check_stack_size()
  // in deeply nested functions
  // output stack_max_size here

【讨论】:

【参考方案3】:

参考 Tobi 的回答:如果在线程初始化时设置变量很困难,您可以随时使用pthread_attr_getstackaddr 获取堆栈的底部。然后,您可以在自己的函数中获取自动变量的地址,以确定此时堆栈的深度。

【讨论】:

以上是关于测量 Linux 多线程应用程序的堆栈使用情况的主要内容,如果未能解决你的问题,请参考以下文章

linux perf 是不是准确测量多线程 C 程序的缓存未命中?

在多线程 C++ 应用程序中测量时间

Linux VM(重型多线程应用程序)的性能改进

如何找到导致cpu飙高的线程堆栈信息

JProfiler 可以测量堆栈深度吗?

如何测量多线程应用程序中的缓存性能?