File: eventcount.stp

package info (click to toggle)
systemtap 4.4-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 38,260 kB
  • sloc: cpp: 77,147; ansic: 61,828; xml: 49,277; exp: 42,244; sh: 11,046; python: 2,772; perl: 2,252; tcl: 1,305; makefile: 1,086; lisp: 105; java: 102; awk: 101; asm: 91; sed: 16
file content (225 lines) | stat: -rwxr-xr-x 6,936 bytes parent folder | download | duplicates (5)
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
#! /usr/bin/env stap

# General event counter / monitor.  Gives a report of event counts/rates on a
# per-process or systemwide basis at script shutdown.
# 
# Invoke with a list of probe point patterns as script command-line arguments:
# stap eventcount.stp 'syscall.*' ...
#
# Optionally, specify process/thread-id to limit analysis:
# stap eventcount.stp -c "CMD ARGS" [...probe points...]
# or stap eventcount.stp -x PID [...probe points...]
# or stap eventcount.stp -G comm=EXECNAME [...probe points...]
#
# Optionally, override periodic screen update, every NNN seconds (default 10)
# stap eventcount.stp -G period=NNN [...probe points...]
# ... or cumulative totals
# stap eventcount.stp -G period=0 [...probe points...]
#
# Optionally, specify cumulative mode for periodic updates
# stap eventcount.stp -G period=NNN -G cumulative=1 [...probe points...]
# stap eventcount.stp -G period=NNN -G cumulative=1 [...probe points...]
#
# Optionally, specify sorting other than by =count
# stap eventcount.stp -G sort=tid [...probe points...]
# stap eventcount.stp -G sort=count [...probe points...]
# stap eventcount.stp -G sort=event [...probe points...]
# stap eventcount.stp -G sort=unsorted [...probe points...]
#
# Optionally, specify a limit for sorted event count reports
# stap eventcount.stp -G lines=100 [...probe points...]
#
# Runtime controls:
#   'j': cycles forwards through the sort options
#   'k': cycles backwards through the sort options
#   'l': toggles cumulative mode
#
#   Pressing enter pauses the reporting and allows a new value for 'comm'
#   to be inputted. Doing so resets all counts. To return to analyzing
#   all processes leave 'comm' blank.

global period=10
global cumulative=0
global comm=""
global sort="count"
global sort_options
global lines=20

probe %($# == 0 || $# > 32 %? begin %: never %)
{
  printf("Please specify between 1 and 32 events to count.\n")
  exit()
}


global c%
global totalc, filteredc

//paramaterize up to 32 arguments
probe %($# >= 1 %? $1 %: never %),
      %($# >= 2 %? $2 %: never %),
      %($# >= 3 %? $3 %: never %),
      %($# >= 4 %? $4 %: never %),
      %($# >= 5 %? $5 %: never %),
      %($# >= 6 %? $6 %: never %),
      %($# >= 7 %? $7 %: never %),
      %($# >= 8 %? $8 %: never %),
      %($# >= 9 %? $9 %: never %),
      %($# >= 10 %? $10 %: never %),
      %($# >= 11 %? $11 %: never %),
      %($# >= 12 %? $12 %: never %),
      %($# >= 13 %? $13 %: never %),
      %($# >= 14 %? $14 %: never %),
      %($# >= 15 %? $15 %: never %),
      %($# >= 16 %? $16 %: never %),
      %($# >= 17 %? $17 %: never %),
      %($# >= 18 %? $18 %: never %),
      %($# >= 19 %? $19 %: never %),
      %($# >= 20 %? $20 %: never %),
      %($# >= 21 %? $21 %: never %),
      %($# >= 22 %? $22 %: never %),
      %($# >= 23 %? $23 %: never %),
      %($# >= 24 %? $24 %: never %),
      %($# >= 25 %? $25 %: never %),
      %($# >= 26 %? $26 %: never %),
      %($# >= 27 %? $27 %: never %),
      %($# >= 28 %? $28 %: never %),
      %($# >= 29 %? $29 %: never %),
      %($# >= 30 %? $30 %: never %),
      %($# >= 31 %? $32 %: never %),
      %($# >= 32 %? $32 %: never %)
{
  totalc <<< 1
  if (target() && ! target_set_pid(pid()))
    next
  if (comm != "" && execname() != comm)
    next
  filteredc <<< 1
  c[sprintf("%s(%d)",execname(),tid()), pn()]<<<1
}

probe begin {
      start_ms = gettimeofday_ms() 
      if (target()) msg = sprintf ("pid %d + children", target())
      else if (comm != "") msg = sprintf ("execname %s", comm)
      else msg = "unfiltered";
      printf("Starting event counting at %s, %s\n",
             tz_ctime(gettimeofday_s()), msg)
      format = sprintf("max %d lines, sorted by %s", lines, sort);
      if (period)
        printf("%s reporting (%s) every %d s\n",
               cumulative ? "Cumulative" : "Incremental",
               format, period)
      else
        printf("One-time cumulative reporting (%s) at script termination (^C)\n",
               format)

      sort_options[0] = "count"
      sort_options[1] = "tid"
      sort_options[2] = "event"
      sort_options[3] = "unsorted"
}
global start_ms


function reportline(tid, name, countstr) {
  // fine-grained control over the column layout here
  printf("%-22s %-15s %s\n", tid, countstr, name)
}

function reportline2(tid, name, count, elapsed_ms) {
  reportline(tid, name,
             sprintf("%d (%d.%02d)", count,
                     (count * 100000 / elapsed_ms)/100,
                     (count * 100000 / elapsed_ms)%100))
}

global input_mode = "char"

function report () {
  elapsed_ms = gettimeofday_ms() - start_ms
  if (elapsed_ms < 0) elapsed_ms=1
  printf("%s time elapsed: %d ms, %d events, %d after filtering.\n",
         (cumulative ? "Cumulative" : "Period"),
         elapsed_ms, @count(totalc), @count(filteredc))

  reportline("TID", "EVENT", "COUNT (Hz)")
  reportline("---", "-----", "----------")
  if (sort == "count")
    foreach([tid, name] in c- limit lines)
      reportline2(tid, name, @count(c[tid,name]), elapsed_ms)
  else if (sort == "tid")
    foreach([tid+, name] in c limit lines)
      reportline2(tid, name, @count(c[tid,name]), elapsed_ms)
  else if (sort == "event")
    foreach([tid, name+] in c limit lines)
      reportline2(tid, name, @count(c[tid,name]), elapsed_ms)
  else # unsorted
    foreach([tid, name] in c limit lines)
      reportline2(tid, name, @count(c[tid,name]), elapsed_ms)
}

probe end {
  report()
  printf("Finished event counting at %s.\n", tz_ctime(gettimeofday_s()))
}

probe timer.s(1) {
      if (period <= 0) next
      if ((gettimeofday_s() % period) == 0) {
         if (input_mode == "char")
		 report()
         if (! cumulative) {
             delete c
             delete filteredc
             delete totalc
             start_ms = gettimeofday_ms()
         }
      }
}

probe input.line {
    if (input_mode != "line")
            next
    // remove newline character
    comm = substr(line, 0, strlen(line) - 1)
    if (comm == "") {
        print("\nNow analyzing all processes")
    } else {
        print("\nNow analyzing process \"" . comm . "\"")
    }
    delete c
    delete filteredc
    delete totalc
}

global idx = 0 // index into sort_options

probe input.char {
     if (input_mode == "line") {
	     print(char)
	     if (char == "\n")
	         input_mode = "char"
     }
     else if (char == "j") {
	     idx = (idx + 1) % 4
	     sort = sort_options[idx]
	     println("Sorting by " . sort)
     }
     else if (char == "k") {
	     idx = idx ? (idx - 1) % 4 : 3
             sort = sort_options[idx]
	     println("Sorting by " . sort)
     }
     else if (char == "l") {
	     cumulative = 1 - cumulative
	     if (cumulative)
		     println("Cumulative mode enabled")
             else
		     println("Cumulative mode disabled")
     }
     else if (char == "\n") {
	     input_mode = "line"
	     println("Please enter a process name:")
     }
}