Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measuring stack usage for Linux multi-threaded app

I'm developing a multi-threaded app for a Linux embedded platform.

At the moment I'm setting the stack size for each thread (via pthread_set_attr) to a fairly large default value. I would like to fine tune that value for each thread to something smaller to reduce my application's memory usage. I could go through the trial and error route of setting each thread's stack size to progressively smaller values until the program crashed, but the application uses ~15 threads each with completely different functionality/attributes so that approach would be extremely time consuming.

I would much rather prefer being able to directly measure each thread's stack usage. Is there some utility people can recommend to do this? (For example, I come from a vxWorks background and using the 'ti' command from the vxWorks shell directly gives stats on the stack usage as well as other useful info on the task status.)

Thanks

like image 909
mtabz Avatar asked Jan 24 '23 03:01

mtabz


2 Answers

Here are two tools that measure (native pthreads) stack usage in Linux applications:

  • Valgrind
  • Stackusage

Valgrind

Usage:

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

Valgrind is a stable and powerful tool, useful not only for measuring stack usage. It may not support all embedded CPU models though.

Stackusage

Usage:

stackusage PROG

Stackusage is a light-weight tool specifically designed for measuring thread stack usage which should be portable for most embedded Linux platforms equipped with glibc. It is likely not as well-tested or mature as Valgrind/drd at this point.

Full disclosure: I'm the author of Stackusage.

like image 119
d99kris Avatar answered Feb 08 '23 21:02

d99kris


I do not know any good tools but as last resort you could include some code in your application to check it, similar to the following:

__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;
}

The check_stack_size() function would have to be called in some of the functions that are most deeply nested.

Then as last statement in the thread you could output stack_max_size to somewhere.

The stack_start variable would have to be initialized at start of your thread:

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
}
like image 39
Tobi Avatar answered Feb 08 '23 21:02

Tobi