基本的なアイデア
/proc/*/task/*/stat から、各threadのcpu使用時間をもってくる。
pstack(gstack)で、各threadのstackをもってくる。sedで一行にするのが肝
コード
thstat
#!/bin/bash
pid=$1
pstack ${pid} | sed -e ":a;N;s/\n\([^T].*\) .* in \(.*\)/ \2/;t a;P;D" | sed "s/Thread .* (Thread .* (LWP \(.*\))): \(.*\)/\1 \2/; s/ from [^ ]*\($\| \)/ /g; s/@@GLIBC[^ ]*//g; s/ ()\($\| \)/--/g; s/([^)]*)/()/g; s/ \[[^]]\+\]/\[\]/g; s/<[^<>]*>/{}/g; s/<[^<>]*>/{}/g; s/<[^<>]*>/{}/g;s/<[^<>]*>/{}/g;s/{}/<>/g; s/ /-/2g " | sort -nk1
while true ; do echo "time $(date +%H:%M:%S)"; cat /proc/${pid}/task/*/stat; sleep 2; done | awk '{if ($1=="time") {times=$2; printf ("\n%s ",times)} else {if ($1 in etime) printf("%d:[%s] ",$1,$14+$15-etime[$1]); etime[$1]=$14+$15}}'
出力例
$ thstat 22930
22930 runtime.futex--runtime.futexsleep--runtime.notesleep--stopm--findrunnable--schedule--runtime.park_m--runtime.mcall--runtime.g0--runtime.mstart--runtime.rt0_go--??--??--??--??--??--
22932 runtime.futex--runtime.futexsleep--runtime.notetsleep_internal--runtime.notetsleep--sysmon--mstart--runtime.mstart--crosscall_amd64--??--??--
22933 runtime.futex--runtime.futexsleep--runtime.notetsleep_internal--runtime.notetsleepg--runtime.signal_recv--os/signal.loop--runtime.goexit--??--
22934 runtime.futex--runtime.futexsleep--runtime.notesleep--stopm--findrunnable--schedule--runtime.park_m--runtime.mcall--??--runtime.mstart--crosscall_amd64--??--??--
22935 runtime.futex--runtime.futexsleep--runtime.notesleep--stopm--findrunnable--schedule--runtime.park_m--runtime.mcall--??--runtime.mstart--crosscall_amd64--??--??--
22936 runtime.futex--runtime.futexsleep--runtime.notetsleep_internal--runtime.notetsleepg--runtime.timerproc--runtime.goexit--??--
22939 runtime.futex--runtime.futexsleep--runtime.notesleep--stopm--findrunnable--schedule--runtime.park_m--runtime.mcall--??--runtime.mstart--crosscall_amd64--??--??--
22940 runtime.epollwait--runtime.netpoll--findrunnable--schedule--runtime.park_m--runtime.mcall--??--runtime.mstart--crosscall_amd64--??--??--
12:41:52
12:41:54 22930:[0] 22932:[0] 22933:[0] 22934:[0] 22935:[0] 22936:[0] 22939:[0] 22940:[0]
12:41:56 22930:[0] 22932:[0] 22933:[0] 22934:[0] 22935:[0] 22936:[0] 22939:[0] 22940:[0]
12:41:58 22930:[0] 22932:[0] 22933:[0] 22934:[0] 22935:[0] 22936:[0] 22939:[0] 22940:[0]