/usr/share/systemtap/tapset/queue_stats.stp is in systemtap-common 2.9-2ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | # qstats.stp: Queue statistics gathering tapset
/* <tapsetdescription>
* The queue_stats tapset provides functions that,
* given notifications of elementary queuing events (wait, run, done),
* tracks averages such as queue length, service and wait times,
* utilization.
*
* The functions qs_wait(), qs_run(), and qs_done() should be called
* from appropriate probes, in sequence.
*
* Functions with the prefix qsq_ are for querying the statistics averaged
* since the first queue operation (or when qsq_start() was called).
* Since statistics are often fractional, a scale parameter is used to
* multiply the result to a more useful scale. For some fractions, a scale
* of 100 will usefully return percentage numbers.
* </tapsetdescription>
*/
# ------------------------------------------------------------------------
# The default timing function: microseconds. This function could
# go into a separate file (say, qstats_qs_time.stp), so that a user
# script can override it with another definition.
/* XXX: docstring */
function qs_time () { return gettimeofday_us () }
# ------------------------------------------------------------------------
global qs_wtime, qs_wlentime, qs_wcount
global qs_rtime, qs_rlentime, qs_rcount
global qs_stime, qs_utime, qs_dcount
# ------------------------------------------------------------------------
function _qs_update (qname) {
now = qs_time ()
then = qs_utime[qname]; if (! then) { then = now }
delta = now-then
qs_wtime[qname] += qs_wcount[qname] ? delta : 0
qs_wlentime[qname] += qs_wcount[qname] * delta
qs_rtime[qname] += qs_rcount[qname] ? delta : 0
qs_rlentime[qname] += qs_rcount[qname] * delta
qs_utime[qname] = now
}
/**
* sfunction qs_wait - Function to record enqueue requests
* @qname: the name of the queue requesting enqueue
*
* Description: This function records that a new request
* was enqueued for the given queue name.
*/
function qs_wait (qname:string) { # enqueueing request
_qs_update (qname)
qs_wcount[qname] ++
}
/**
* sfunction qs_run - Function to record being moved from wait queue to being serviced
* @qname: the name of the service being moved and started
*
* Description: This function records that the previous enqueued
* request was removed from the given wait queue and is now
* being serviced.
*/
function qs_run (qname:string) { # starting to service request
_qs_update (qname)
if (qs_wcount[qname] > 0) {
qs_wcount[qname] --
qs_rcount[qname] ++
}
}
/**
* sfunction qs_done - Function to record finishing request
* @qname: the name of the service that finished
*
* Description: This function records that a request
* originally from the given queue has completed being
* serviced.
*/
function qs_done (qname:string) { # done servicing request
_qs_update (qname)
if (qs_rcount[qname] > 0) {
qs_rcount[qname] --
qs_dcount[qname] ++
}
}
# ------------------------------------------------------------------------
/**
* sfunction qsq_start - Function to reset the stats for a queue
* @qname: the name of the service that finished
*
* Description: This function resets the statistics counters for the given
* queue, and restarts tracking from the moment the function was called.
* This function is also used to create intialize a queue.
*/
function qsq_start (qname:string) { # reset statistics for new baseline
qs_rcount[qname] = 0
delete qs_rtime[qname]
delete qs_rlentime[qname]
qs_wcount[qname] = 0
delete qs_wtime[qname]
delete qs_wlentime[qname]
delete qs_dcount[qname]
delete qs_utime[qname]
qs_stime[qname] = qs_time ()
}
# ------------------------------------------------------------------------
# Various query functions. Each returns the average, taken over the time
# interval from the last qsq_start(). Most deal with fractions, and so
# also take a scale parameter (use 100 for percent).
/**
* sfunction qsq_utilization - Fraction of time that any request was being serviced
* @qname: queue name
* @scale: scale variable to take account for interval fraction
*
* Description: This function returns the average time in microseconds
* that at least one request was being serviced.
*/
function qsq_utilization:long (qname:string, scale:long) {
_qs_update (qname)
elapsed = qs_time() - qs_stime[qname]
return (scale * qs_rtime[qname]) / elapsed
}
# fraction of time that any request was blocked in the wait queue
/**
* sfunction qsq_blocked - Returns the time reqest was on the wait queue
* @qname: queue name
* @scale: scale variable to take account for interval fraction
*
* Description: This function returns the fraction of elapsed time during
* which one or more requests were on the wait queue.
*/
function qsq_blocked:long (qname:string, scale:long) {
_qs_update (qname)
elapsed = qs_time() - qs_stime[qname]
return (scale * qs_wtime[qname]) / elapsed
}
# length of wait queue
/**
* sfunction qsq_wait_queue_length - length of wait queue
* @qname: queue name
* @scale: scale variable to take account for interval fraction
*
* Description: This function returns the average length of the wait queue
*/
function qsq_wait_queue_length:long (qname:string, scale:long) {
_qs_update (qname)
elapsed = qs_time() - qs_stime[qname]
return (scale * qs_wlentime[qname]) / elapsed
}
/**
* sfunction qsq_service_time - Amount of time per request service
* @qname: queue name
* @scale: scale variable to take account for interval fraction
*
* Description: This function returns the average time in microseconds
* required to service a request once it is removed from the wait queue.
*/
function qsq_service_time:long (qname:string, scale:long) {
_qs_update (qname)
return (scale * qs_rlentime[qname]) / qs_dcount[qname]
}
/**
* sfunction qsq_wait_time - Amount of time in queue + service per request
* @qname: queue name
* @scale: scale variable to take account for interval fraction
*
* Description: This function returns the average time in microseconds
* that it took for a request to be serviced (qs_wait() to qa_done()).
*/
function qsq_wait_time:long (qname:string, scale:long) {
_qs_update (qname)
return (scale * (qs_rlentime[qname] + qs_wlentime[qname]))
/ qs_dcount[qname]
}
/**
* sfunction qsq_throughput - Number of requests served per unit time
* @qname: queue name
* @scale: scale variable to take account for interval fraction
*
* Description: This function returns the average number or requests
* served per microsecond.
*/
function qsq_throughput:long (qname:string, scale:long) {
_qs_update (qname)
elapsed = qs_time() - qs_stime[qname]
return (scale * qs_dcount[qname]) / elapsed
}
# ------------------------------------------------------------------------
/**
* sfunction qsq_print - Prints a line of statistics for the given queue
* @qname: queue name
*
* Description: This function prints a line containing the following
* statistics for the given queue:
* the queue name,
* the average rate of requests per second,
* the average wait queue length,
* the average time on the wait queue,
* the average time to service a request,
* the percentage of time the wait queue was used,
* and the percentage of time request was being serviced.
*/
function qsq_print (qname:string) {
qt = qsq_throughput (qname, 1000000000) # 1000 * (number of requests served per second)
qwl = qsq_wait_queue_length (qname, 1000)
printf("%s: %d.%03d ops/s, %d.%03d qlen, %d await, %d svctm, %d%% wait, %d%% util\n",
qname,
qt/1000, qt%1000,
qwl/1000, qwl%1000,
qsq_wait_time (qname, 1),
qsq_service_time (qname, 1),
qsq_blocked (qname, 100),
qsq_utilization (qname, 100))
}
/* What follows in an example form src/testsuite/systemtap.samples/queue_demo.stp
* It uses the randomize feature of the timer probe to simulate queuing activity.
*
* probe begin {
* qsq_start ("block-read")
* qsq_start ("block-write")
* }
*
* probe timer.ms(3500), end {
* qsq_print ("block-read")
* qsq_start ("block-read")
* qsq_print ("block-write")
* qsq_start ("block-write")
* }
*
* probe timer.ms(10000) {
* exit()
* }
*
* // synthesize queue work/service using three randomized "threads" for each queue.
* global tc
*
* function qs_doit (thread, name) {
* n = tc[thread] = (tc[thread]+1) % 3 //per-thread state counter
* if (n==1) qs_wait (name)
* else if (n==2) qs_run (name)
* else if (n==0) qs_done (name)
* }
*
* probe timer.ms(100).randomize(100) { qs_doit (0, "block-read") }
* probe timer.ms(100).randomize(100) { qs_doit (1, "block-read") }
* probe timer.ms(100).randomize(100) { qs_doit (2, "block-read") }
* probe timer.ms(100).randomize(100) { qs_doit (3, "block-write") }
* probe timer.ms(100).randomize(100) { qs_doit (4, "block-write") }
* probe timer.ms(100).randomize(100) { qs_doit (5, "block-write") }
*
* //This prints:
* block-read: 9 ops/s, 1.090 qlen, 215749 await, 96382 svctm, 69% wait, 64% util
* block-write: 9 ops/s, 0.992 qlen, 208485 await, 103150 svctm, 69% wait, 61% util
* block-read: 9 ops/s, 0.968 qlen, 197411 await, 97762 svctm, 63% wait, 63% util
* block-write: 8 ops/s, 0.930 qlen, 202414 await, 93870 svctm, 60% wait, 56% util
* block-read: 8 ops/s, 0.744 qlen, 192957 await, 99995 svctm, 58% wait, 62% util
* block-write: 9 ops/s, 0.861 qlen, 193857 await, 101573 svctm, 56% wait, 64% util
*/
|