|  | #! /usr/bin/env stap | 
|  |  | 
|  | # ------------------------------------------------------------------------ | 
|  | # data collection | 
|  |  | 
|  | # disk I/O stats | 
|  | probe begin { qnames["ioblock"] ++; qsq_start ("ioblock") } | 
|  | probe ioblock.request { if (pid && pid() == pid) { qs_wait ("ioblock") qs_run("ioblock") }} | 
|  | probe ioblock.end { if (pid && pid() == pid) { qs_done ("ioblock") }} | 
|  |  | 
|  | # CPU utilization | 
|  | probe begin { qnames["cpu"] ++; qsq_start ("cpu") } | 
|  | probe scheduler.cpu_on { if (pid && pid() == pid) { if (!idle) {qs_wait ("cpu") qs_run ("cpu") }}} | 
|  | probe scheduler.cpu_off { if (pid && pid() == pid) { if (!idle) qs_done ("cpu") }} | 
|  |  | 
|  |  | 
|  | # ------------------------------------------------------------------------ | 
|  | # utilization history tracking | 
|  |  | 
|  | global N, pid, threadstacks, threadcounters, reads, writes | 
|  | global qnames | 
|  | global counter | 
|  | probe begin { | 
|  | N = 50; | 
|  | pid = 0; | 
|  | reads = 0; | 
|  | writes = 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | function qsq_util_reset(q) { | 
|  | u=qsq_utilization (q, 100) | 
|  | qsq_start (q) | 
|  | return u | 
|  | } | 
|  |  | 
|  |  | 
|  | probe process(@1).function("*").call { | 
|  | if (pid == 0) { | 
|  | pid = pid(); | 
|  | } | 
|  | if (! threadcounters[tid()] ) { | 
|  | threadstacks[tid()] = probefunc(); | 
|  | } | 
|  | threadcounters[tid()]++; | 
|  | } | 
|  |  | 
|  | probe vfs.read.return { | 
|  | if (pid() == pid) { | 
|  | if ($return>0) { | 
|  | reads += $return; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | probe vfs.write.return { | 
|  | if (pid() == pid) { | 
|  | if ($return>0) { | 
|  | writes += $return; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | probe process(@1).function("*").return { | 
|  | threadcounters[tid()]--; | 
|  | if (! threadcounters[tid()]) { | 
|  | delete(threadcounters[tid()]); | 
|  | delete(threadstacks[tid()]); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | # ------------------------------------------------------------------------ | 
|  | # general gnuplot graphical report generation | 
|  |  | 
|  | probe timer.ms(50) { | 
|  | printf("--\n"); | 
|  | printf("%d, %d, %d, %d, %d, %d, %d, %d\n", counter, qsq_util_reset("cpu"), qsq_util_reset("ioblock"), proc_mem_size_pid(pid) * mem_page_size(), proc_mem_data_pid(pid) * mem_page_size(), reads + writes, reads, writes); | 
|  | foreach (tid in threadcounters) { | 
|  | printf("%d:%s\n", tid, threadstacks[tid]); | 
|  | } | 
|  | reads = 0; | 
|  | writes = 0; | 
|  | counter++; | 
|  | } |