注意和ptrace(ptrace()系统调用提供了一个方法,该方法使一个程序(追踪者)可以观察和控制另外一个程序(被追踪者)的执行,并检查和改变被追踪者的内存及寄存器。它主要用于实现断点调试和追踪系统调用。GDB的工作机制)区分
和jstack一样, pstack亦能展现进程的线程堆栈快照, 非常方便验证和性能评估.
pstack的作用, 大致可以归纳如下:
1). 查看线程数(比pstree, 包含了详细的堆栈信息)
2). 能简单验证是否按照预定的调用顺序/调用栈执行
3). 采用高频率多次采样使用时, 能发现程序当前的阻塞在哪里, 以及性能消耗点在哪里?
4). 能反映出疑似的死锁现象(多个线程同时在wait lock, 具体需要进一步验证)
当然还能举例更多的作用, 相信使用过jstack的coder, 必然深以为然.
pstack原理:
pstack是/usr/bin/gstack的软链接, 而gstack本身是基于gdb封装的shell脚本.
最核心的片段, backtrace=”thread apply all bt”
shell采用了here document的方式, 完成了GDB的交互工作(注意EOF标识, 及范围内的交互命令).
重要的是输入thread apply all bt这个交互命令. 该命令要求输出所有的线程堆栈信息.
对GDB输出的结果, 通过管道并借助sed命令进行了替换和过滤.
`#!/bin/bash
if test $# -ne 1; then
echo “Usage: basename $0 .sh
exit 1
fi
if test ! -r /proc/$1; then
echo “Process $1 not found.” 1>&2
exit 1
fi
backtrace=”bt”
if test -d /proc/$1/task ; then
# Newer kernel; has a task/ directory.
if test /bin/ls /proc/$1/task | /usr/bin/wc -l
-gt 1 2>/dev/null ; then
backtrace=”thread apply all bt”
fi
elif test -f /proc/$1/maps ; then
# Older kernel; go by it loading libpthread.
if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
backtrace=”thread apply all bt”
fi
fi
GDB=${GDB:-/usr/bin/gdb}
if $GDB -nx –quiet –batch –readnever > /dev/null 2>&1; then
readnever=–readnever
else
readnever=
fi
$GDB –quiet $readnever -nx /proc/$1/exe $1 «EOF 2>&1 |
$backtrace
EOF
/bin/sed -n
-e ‘s/^(gdb) //’
-e ‘/^#/p’
-e ‘/^Thread/p’
`
利用pstack 和 strace分析程序在哪里耗时
ps 查找进程的pid
pstack 打印进程或者线程的栈信息
strace 统计每一步系统调用花费的时间
ps -aux | grep nws 可以看出nws的pid为171211 |
1.死机后,输入:
info threads ——- 查看所有thread信息