X-Git-Url: https://git.xandkar.net/?a=blobdiff_plain;f=home%2Fbin%2Fps2dot;h=c6bf85f325434fe727d5a359894ecada532dd45b;hb=059851a97130fc338a0c0a10977ed78e53356fcd;hp=c8db891f98cafce46d83f42ab258f2d2dcdded83;hpb=5259a527ae1db5a663fd579398468f8a2062518c;p=khome.git diff --git a/home/bin/ps2dot b/home/bin/ps2dot index c8db891..c6bf85f 100755 --- a/home/bin/ps2dot +++ b/home/bin/ps2dot @@ -1,65 +1,134 @@ #! /bin/sh +set -e + usage() { echo "EXAMPLE (whole tree) : $0 | neato -T png > ps.png && open ps.png" echo "EXAMPLE (user clusters): $0 | sdp -T png > ps.png && open ps.png" } -compile() { +ps2dot() { awk -v kernel="$(uname -v)" -v whoami="$(whoami)" \ ' function num_scale(src_cur, src_max, dst_min, dst_max) { return dst_min + ((src_cur * (dst_max - dst_min)) / src_max) } - function vert_print(v, _color, _fontcolor) { + function vert_print(v, _color, _fontcolor, _shape, _state, _size, _height, _label, _label_base, _label_ext) { + _state = child2state[v] + _style = "filled,solid" + + # ----------------------------------------------------------------- + # Sleeping/idling + # ----------------------------------------------------------------- + # D uninterruptible sleep (usually IO) + if (_state == "D") { + _shape = "circle" + # I Idle kernel thread + } else if (_state == "I") { + _shape = "circle" + # S interruptible sleep (waiting for an event to complete) + } else if (_state == "S") { + _shape = "circle" + # ----------------------------------------------------------------- + # Running + # ----------------------------------------------------------------- + # R running or runnable (on run queue) + } else if (_state == "R") { + _shape = "rarrow" + # ----------------------------------------------------------------- + # Stopped + # ----------------------------------------------------------------- + # T stopped by job control signal + } else if (_state == "T") { + _shape = "square" + # t stopped by debugger during the tracing + } else if (_state == "t") { + _shape = "square" + # ----------------------------------------------------------------- + # Dead + # ----------------------------------------------------------------- + # Z defunct ("zombie") process, terminated but not reaped by its parent + } else if (_state == "Z") { + _shape = "Msquare" + _style = "solid" + # ----------------------------------------------------------------- + # UNKNOWN STATE + # ----------------------------------------------------------------- + } else { + _shape = "doublecircle" + } + _color =\ num_scale(\ - child2nice[v] + 20, - 20 + 20, - COLORSCHEME_MIN, - COLORSCHEME_MAX\ + child2cpu[v], + max_cpu, + VERT_COLORSCHEME_MAX, + VERT_COLORSCHEME_MIN\ ) + _size =\ + num_scale(\ + child2mem[v], + max_mem, + 1, + 4\ + ) / 4 + _height = _size + _width = _size _fontcolor = \ - _color == COLORSCHEME_MAX || _color == COLORSCHEME_MIN \ - ? sprintf("/%s/%d", COLORSCHEME, COLORSCHEME_MID) \ + _color == VERT_COLORSCHEME_MAX || _color == VERT_COLORSCHEME_MIN \ + ? sprintf("/%s/%d", VERT_COLORSCHEME, VERT_COLORSCHEME_MID) \ : sprintf("/%s/%d", "greys9", 9) + _fontcolor = \ + _size < 0.5 \ + ? sprintf("/%s/%d", "greys9", 9) \ + : _fontcolor + _label_base = \ + sprintf("%s\n%d", child2comm[v], v) + _label_ext = \ + _size >= 0.5 \ + ? sprintf("\ncpu: %.1f%%\nmem: %.1f%%", child2cpu[v], child2mem[v]) \ + : "" + _label = _label_base _label_ext printf(\ "\"%d\"\ [ fontsize=8 \ - , style=filled \ + , fixedsize=true \ + , height=%f \ + , width=%f \ + , border=1 \ + , style=\"%s\" \ , fontname=Helvetica \ - , shape=ellipse \ - , label=\"%s\n%d\" \ - , color=\"/%s/%d\" \ + , label=\"%s\" \ + , shape=\"%s\" \ + , fillcolor=\"/%s/%d\" \ , fontcolor=\"%s\" \ ];", v, - child2cmd[v], - v, - COLORSCHEME, + _height, + _width, + _style, + _label, + _shape, + VERT_COLORSCHEME, _color, _fontcolor\ ) } - function edge_print(child, _parent, _color, _colorscheme) { + function edge_print(child, _parent) { _parent = child2parent[child] - _colorscheme = "greys9" - _color = 3 printf(\ "\"%s\" -> \"%s\"\ [ fontsize=8 \ , fontname=Helvetica \ , len=2.0 \ - , colorscheme=%s \ - , color=%d \ + , color=\"%s\" \ ];\n", _parent, child, - _colorscheme, - _color\ + EDGE_COLOR\ ) } @@ -68,6 +137,7 @@ compile() { # - rdbu11 # - rdbu9 # - rdbu8 + # - rdylgn10 # 3 - 11 # Light->Dark gradual colorschemes: # - reds9 @@ -77,12 +147,14 @@ compile() { # - bupu9 # - greys9 - COLORSCHEME_MIN = 1 - COLORSCHEME_MID = 5 - COLORSCHEME_MAX = 9 - COLORSCHEME = sprintf("rdbu%d", COLORSCHEME_MAX) + VERT_COLORSCHEME_MIN = 1 + VERT_COLORSCHEME_MID = 4 + VERT_COLORSCHEME_MAX = 8 + VERT_COLORSCHEME = "rdylgn10" + + EDGE_COLOR = "/ylorbr9/3" - child2cmd[0] = "swapper/sched" + child2comm[0] = "swapper/sched" } NR > 1 { @@ -95,8 +167,13 @@ compile() { child2user_id[$1] = $3 child2user_name[$1] = $4 child2nice[$1] = $5 - child2cmd[$1] = $6 + child2state[$1] = $6 + child2cpu[$1] = $7 + child2mem[$1] = $8 + child2comm[$1] = $9 user_names[$4] = 1 + max_cpu = $7 > max_cpu ? $7 : max_cpu + max_mem = $8 > max_mem ? $8 : max_mem } END { @@ -106,8 +183,7 @@ compile() { print "fontsize=8;"; print "fontname=Helvetica;"; print "label=\"" kernel "\";"; - printf "colorscheme=%s;\n", COLORSCHEME - print "fontcolor=9;" + print "fontcolor=\"/greys9/9\";" ##### Vertices (clustered by user) for (user_name in user_names) { @@ -120,7 +196,7 @@ compile() { } ##### Vertices (without a user) - for (c in child2cmd) + for (c in child2comm) if (!child2user_name[c]) vert_print(c) @@ -136,18 +212,31 @@ compile() { procs() { if [ "$(uname)" = 'Linux' ]; then - ps -eo 'pid,ppid,euid,euser,nice,comm' + ps -eo 'pid,ppid,euid,euser,nice,s,%cpu,%mem,comm' else - ps -eco 'pid,ppid,euid,euser,nice,comm' + ps -eco 'pid,ppid,euid,euser,nice,s,%cpu,%mem,comm' fi } main() { case "$1" in - '--help') usage + '--help') + usage ;; - *) procs | grep "$1" | compile + *) + timestamp="$(date +'%Y-%m-%d_%H:%M:%S%z')" + host="$(hostname)" + kernel="$(uname -s | awk '{print tolower($0)}')" + filename_base=$(mktemp "ps.$host.$kernel.$timestamp.XXXXX") + file_log="$filename_base.log" + file_dot="$filename_base.dot" + mv "$filename_base" "$file_log" + procs | grep "$1" | ps2dot 2> "$file_log" > "$file_dot" + time neato -T png "$file_dot" 2> "$file_log" > "$filename_base.neato.png" + time fdp -T png "$file_dot" 2> "$file_log" > "$filename_base.fdp.png" + time dot -T png "$file_dot" 2> "$file_log" > "$filename_base.dot.png" + ls -1 "$filename_base"* ;; esac }