xref: /OK3568_Linux_fs/kernel/tools/perf/Documentation/perf-script-python.txt (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyunperf-script-python(1)
2*4882a593Smuzhiyun====================
3*4882a593Smuzhiyun
4*4882a593SmuzhiyunNAME
5*4882a593Smuzhiyun----
6*4882a593Smuzhiyunperf-script-python - Process trace data with a Python script
7*4882a593Smuzhiyun
8*4882a593SmuzhiyunSYNOPSIS
9*4882a593Smuzhiyun--------
10*4882a593Smuzhiyun[verse]
11*4882a593Smuzhiyun'perf script' [-s [Python]:script[.py] ]
12*4882a593Smuzhiyun
13*4882a593SmuzhiyunDESCRIPTION
14*4882a593Smuzhiyun-----------
15*4882a593Smuzhiyun
16*4882a593SmuzhiyunThis perf script option is used to process perf script data using perf's
17*4882a593Smuzhiyunbuilt-in Python interpreter.  It reads and processes the input file and
18*4882a593Smuzhiyundisplays the results of the trace analysis implemented in the given
19*4882a593SmuzhiyunPython script, if any.
20*4882a593Smuzhiyun
21*4882a593SmuzhiyunA QUICK EXAMPLE
22*4882a593Smuzhiyun---------------
23*4882a593Smuzhiyun
24*4882a593SmuzhiyunThis section shows the process, start to finish, of creating a working
25*4882a593SmuzhiyunPython script that aggregates and extracts useful information from a
26*4882a593Smuzhiyunraw perf script stream.  You can avoid reading the rest of this
27*4882a593Smuzhiyundocument if an example is enough for you; the rest of the document
28*4882a593Smuzhiyunprovides more details on each step and lists the library functions
29*4882a593Smuzhiyunavailable to script writers.
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunThis example actually details the steps that were used to create the
32*4882a593Smuzhiyun'syscall-counts' script you see when you list the available perf script
33*4882a593Smuzhiyunscripts via 'perf script -l'.  As such, this script also shows how to
34*4882a593Smuzhiyunintegrate your script into the list of general-purpose 'perf script'
35*4882a593Smuzhiyunscripts listed by that command.
36*4882a593Smuzhiyun
37*4882a593SmuzhiyunThe syscall-counts script is a simple script, but demonstrates all the
38*4882a593Smuzhiyunbasic ideas necessary to create a useful script.  Here's an example
39*4882a593Smuzhiyunof its output (syscall names are not yet supported, they will appear
40*4882a593Smuzhiyunas numbers):
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun----
43*4882a593Smuzhiyunsyscall events:
44*4882a593Smuzhiyun
45*4882a593Smuzhiyunevent                                          count
46*4882a593Smuzhiyun----------------------------------------  -----------
47*4882a593Smuzhiyunsys_write                                     455067
48*4882a593Smuzhiyunsys_getdents                                    4072
49*4882a593Smuzhiyunsys_close                                       3037
50*4882a593Smuzhiyunsys_swapoff                                     1769
51*4882a593Smuzhiyunsys_read                                         923
52*4882a593Smuzhiyunsys_sched_setparam                               826
53*4882a593Smuzhiyunsys_open                                         331
54*4882a593Smuzhiyunsys_newfstat                                     326
55*4882a593Smuzhiyunsys_mmap                                         217
56*4882a593Smuzhiyunsys_munmap                                       216
57*4882a593Smuzhiyunsys_futex                                        141
58*4882a593Smuzhiyunsys_select                                       102
59*4882a593Smuzhiyunsys_poll                                          84
60*4882a593Smuzhiyunsys_setitimer                                     12
61*4882a593Smuzhiyunsys_writev                                         8
62*4882a593Smuzhiyun15                                                 8
63*4882a593Smuzhiyunsys_lseek                                          7
64*4882a593Smuzhiyunsys_rt_sigprocmask                                 6
65*4882a593Smuzhiyunsys_wait4                                          3
66*4882a593Smuzhiyunsys_ioctl                                          3
67*4882a593Smuzhiyunsys_set_robust_list                                1
68*4882a593Smuzhiyunsys_exit                                           1
69*4882a593Smuzhiyun56                                                 1
70*4882a593Smuzhiyunsys_access                                         1
71*4882a593Smuzhiyun----
72*4882a593Smuzhiyun
73*4882a593SmuzhiyunBasically our task is to keep a per-syscall tally that gets updated
74*4882a593Smuzhiyunevery time a system call occurs in the system.  Our script will do
75*4882a593Smuzhiyunthat, but first we need to record the data that will be processed by
76*4882a593Smuzhiyunthat script.  Theoretically, there are a couple of ways we could do
77*4882a593Smuzhiyunthat:
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun- we could enable every event under the tracing/events/syscalls
80*4882a593Smuzhiyun  directory, but this is over 600 syscalls, well beyond the number
81*4882a593Smuzhiyun  allowable by perf.  These individual syscall events will however be
82*4882a593Smuzhiyun  useful if we want to later use the guidance we get from the
83*4882a593Smuzhiyun  general-purpose scripts to drill down and get more detail about
84*4882a593Smuzhiyun  individual syscalls of interest.
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun- we can enable the sys_enter and/or sys_exit syscalls found under
87*4882a593Smuzhiyun  tracing/events/raw_syscalls.  These are called for all syscalls; the
88*4882a593Smuzhiyun  'id' field can be used to distinguish between individual syscall
89*4882a593Smuzhiyun  numbers.
90*4882a593Smuzhiyun
91*4882a593SmuzhiyunFor this script, we only need to know that a syscall was entered; we
92*4882a593Smuzhiyundon't care how it exited, so we'll use 'perf record' to record only
93*4882a593Smuzhiyunthe sys_enter events:
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun----
96*4882a593Smuzhiyun# perf record -a -e raw_syscalls:sys_enter
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun^C[ perf record: Woken up 1 times to write data ]
99*4882a593Smuzhiyun[ perf record: Captured and wrote 56.545 MB perf.data (~2470503 samples) ]
100*4882a593Smuzhiyun----
101*4882a593Smuzhiyun
102*4882a593SmuzhiyunThe options basically say to collect data for every syscall event
103*4882a593Smuzhiyunsystem-wide and multiplex the per-cpu output into a single stream.
104*4882a593SmuzhiyunThat single stream will be recorded in a file in the current directory
105*4882a593Smuzhiyuncalled perf.data.
106*4882a593Smuzhiyun
107*4882a593SmuzhiyunOnce we have a perf.data file containing our data, we can use the -g
108*4882a593Smuzhiyun'perf script' option to generate a Python script that will contain a
109*4882a593Smuzhiyuncallback handler for each event type found in the perf.data trace
110*4882a593Smuzhiyunstream (for more details, see the STARTER SCRIPTS section).
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun----
113*4882a593Smuzhiyun# perf script -g python
114*4882a593Smuzhiyungenerated Python script: perf-script.py
115*4882a593Smuzhiyun
116*4882a593SmuzhiyunThe output file created also in the current directory is named
117*4882a593Smuzhiyunperf-script.py.  Here's the file in its entirety:
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun# perf script event handlers, generated by perf script -g python
120*4882a593Smuzhiyun# Licensed under the terms of the GNU GPL License version 2
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun# The common_* event handler fields are the most useful fields common to
123*4882a593Smuzhiyun# all events.  They don't necessarily correspond to the 'common_*' fields
124*4882a593Smuzhiyun# in the format files.  Those fields not available as handler params can
125*4882a593Smuzhiyun# be retrieved using Python functions of the form common_*(context).
126*4882a593Smuzhiyun# See the perf-script-python Documentation for the list of available functions.
127*4882a593Smuzhiyun
128*4882a593Smuzhiyunimport os
129*4882a593Smuzhiyunimport sys
130*4882a593Smuzhiyun
131*4882a593Smuzhiyunsys.path.append(os.environ['PERF_EXEC_PATH'] + \
132*4882a593Smuzhiyun	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
133*4882a593Smuzhiyun
134*4882a593Smuzhiyunfrom perf_trace_context import *
135*4882a593Smuzhiyunfrom Core import *
136*4882a593Smuzhiyun
137*4882a593Smuzhiyundef trace_begin():
138*4882a593Smuzhiyun	print "in trace_begin"
139*4882a593Smuzhiyun
140*4882a593Smuzhiyundef trace_end():
141*4882a593Smuzhiyun	print "in trace_end"
142*4882a593Smuzhiyun
143*4882a593Smuzhiyundef raw_syscalls__sys_enter(event_name, context, common_cpu,
144*4882a593Smuzhiyun	common_secs, common_nsecs, common_pid, common_comm,
145*4882a593Smuzhiyun	id, args):
146*4882a593Smuzhiyun		print_header(event_name, common_cpu, common_secs, common_nsecs,
147*4882a593Smuzhiyun			common_pid, common_comm)
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun		print "id=%d, args=%s\n" % \
150*4882a593Smuzhiyun		(id, args),
151*4882a593Smuzhiyun
152*4882a593Smuzhiyundef trace_unhandled(event_name, context, event_fields_dict):
153*4882a593Smuzhiyun		print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
154*4882a593Smuzhiyun
155*4882a593Smuzhiyundef print_header(event_name, cpu, secs, nsecs, pid, comm):
156*4882a593Smuzhiyun	print "%-20s %5u %05u.%09u %8u %-20s " % \
157*4882a593Smuzhiyun	(event_name, cpu, secs, nsecs, pid, comm),
158*4882a593Smuzhiyun----
159*4882a593Smuzhiyun
160*4882a593SmuzhiyunAt the top is a comment block followed by some import statements and a
161*4882a593Smuzhiyunpath append which every perf script script should include.
162*4882a593Smuzhiyun
163*4882a593SmuzhiyunFollowing that are a couple generated functions, trace_begin() and
164*4882a593Smuzhiyuntrace_end(), which are called at the beginning and the end of the
165*4882a593Smuzhiyunscript respectively (for more details, see the SCRIPT_LAYOUT section
166*4882a593Smuzhiyunbelow).
167*4882a593Smuzhiyun
168*4882a593SmuzhiyunFollowing those are the 'event handler' functions generated one for
169*4882a593Smuzhiyunevery event in the 'perf record' output.  The handler functions take
170*4882a593Smuzhiyunthe form subsystem__event_name, and contain named parameters, one for
171*4882a593Smuzhiyuneach field in the event; in this case, there's only one event,
172*4882a593Smuzhiyunraw_syscalls__sys_enter().  (see the EVENT HANDLERS section below for
173*4882a593Smuzhiyunmore info on event handlers).
174*4882a593Smuzhiyun
175*4882a593SmuzhiyunThe final couple of functions are, like the begin and end functions,
176*4882a593Smuzhiyungenerated for every script.  The first, trace_unhandled(), is called
177*4882a593Smuzhiyunevery time the script finds an event in the perf.data file that
178*4882a593Smuzhiyundoesn't correspond to any event handler in the script.  This could
179*4882a593Smuzhiyunmean either that the record step recorded event types that it wasn't
180*4882a593Smuzhiyunreally interested in, or the script was run against a trace file that
181*4882a593Smuzhiyundoesn't correspond to the script.
182*4882a593Smuzhiyun
183*4882a593SmuzhiyunThe script generated by -g option simply prints a line for each
184*4882a593Smuzhiyunevent found in the trace stream i.e. it basically just dumps the event
185*4882a593Smuzhiyunand its parameter values to stdout.  The print_header() function is
186*4882a593Smuzhiyunsimply a utility function used for that purpose.  Let's rename the
187*4882a593Smuzhiyunscript and run it to see the default output:
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun----
190*4882a593Smuzhiyun# mv perf-script.py syscall-counts.py
191*4882a593Smuzhiyun# perf script -s syscall-counts.py
192*4882a593Smuzhiyun
193*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847582083     7506 perf                  id=1, args=
194*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847595764     7506 perf                  id=1, args=
195*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847620860     7506 perf                  id=1, args=
196*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847710478     6533 npviewer.bin          id=78, args=
197*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847719204     6533 npviewer.bin          id=142, args=
198*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847755445     6533 npviewer.bin          id=3, args=
199*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847775601     6533 npviewer.bin          id=3, args=
200*4882a593Smuzhiyunraw_syscalls__sys_enter     1 00840.847781820     6533 npviewer.bin          id=3, args=
201*4882a593Smuzhiyun.
202*4882a593Smuzhiyun.
203*4882a593Smuzhiyun.
204*4882a593Smuzhiyun----
205*4882a593Smuzhiyun
206*4882a593SmuzhiyunOf course, for this script, we're not interested in printing every
207*4882a593Smuzhiyuntrace event, but rather aggregating it in a useful way.  So we'll get
208*4882a593Smuzhiyunrid of everything to do with printing as well as the trace_begin() and
209*4882a593Smuzhiyuntrace_unhandled() functions, which we won't be using.  That leaves us
210*4882a593Smuzhiyunwith this minimalistic skeleton:
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun----
213*4882a593Smuzhiyunimport os
214*4882a593Smuzhiyunimport sys
215*4882a593Smuzhiyun
216*4882a593Smuzhiyunsys.path.append(os.environ['PERF_EXEC_PATH'] + \
217*4882a593Smuzhiyun	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
218*4882a593Smuzhiyun
219*4882a593Smuzhiyunfrom perf_trace_context import *
220*4882a593Smuzhiyunfrom Core import *
221*4882a593Smuzhiyun
222*4882a593Smuzhiyundef trace_end():
223*4882a593Smuzhiyun	print "in trace_end"
224*4882a593Smuzhiyun
225*4882a593Smuzhiyundef raw_syscalls__sys_enter(event_name, context, common_cpu,
226*4882a593Smuzhiyun	common_secs, common_nsecs, common_pid, common_comm,
227*4882a593Smuzhiyun	id, args):
228*4882a593Smuzhiyun----
229*4882a593Smuzhiyun
230*4882a593SmuzhiyunIn trace_end(), we'll simply print the results, but first we need to
231*4882a593Smuzhiyungenerate some results to print.  To do that we need to have our
232*4882a593Smuzhiyunsys_enter() handler do the necessary tallying until all events have
233*4882a593Smuzhiyunbeen counted.  A hash table indexed by syscall id is a good way to
234*4882a593Smuzhiyunstore that information; every time the sys_enter() handler is called,
235*4882a593Smuzhiyunwe simply increment a count associated with that hash entry indexed by
236*4882a593Smuzhiyunthat syscall id:
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun----
239*4882a593Smuzhiyun  syscalls = autodict()
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun  try:
242*4882a593Smuzhiyun    syscalls[id] += 1
243*4882a593Smuzhiyun  except TypeError:
244*4882a593Smuzhiyun    syscalls[id] = 1
245*4882a593Smuzhiyun----
246*4882a593Smuzhiyun
247*4882a593SmuzhiyunThe syscalls 'autodict' object is a special kind of Python dictionary
248*4882a593Smuzhiyun(implemented in Core.py) that implements Perl's 'autovivifying' hashes
249*4882a593Smuzhiyunin Python i.e. with autovivifying hashes, you can assign nested hash
250*4882a593Smuzhiyunvalues without having to go to the trouble of creating intermediate
251*4882a593Smuzhiyunlevels if they don't exist e.g syscalls[comm][pid][id] = 1 will create
252*4882a593Smuzhiyunthe intermediate hash levels and finally assign the value 1 to the
253*4882a593Smuzhiyunhash entry for 'id' (because the value being assigned isn't a hash
254*4882a593Smuzhiyunobject itself, the initial value is assigned in the TypeError
255*4882a593Smuzhiyunexception.  Well, there may be a better way to do this in Python but
256*4882a593Smuzhiyunthat's what works for now).
257*4882a593Smuzhiyun
258*4882a593SmuzhiyunPutting that code into the raw_syscalls__sys_enter() handler, we
259*4882a593Smuzhiyuneffectively end up with a single-level dictionary keyed on syscall id
260*4882a593Smuzhiyunand having the counts we've tallied as values.
261*4882a593Smuzhiyun
262*4882a593SmuzhiyunThe print_syscall_totals() function iterates over the entries in the
263*4882a593Smuzhiyundictionary and displays a line for each entry containing the syscall
264*4882a593Smuzhiyunname (the dictionary keys contain the syscall ids, which are passed to
265*4882a593Smuzhiyunthe Util function syscall_name(), which translates the raw syscall
266*4882a593Smuzhiyunnumbers to the corresponding syscall name strings).  The output is
267*4882a593Smuzhiyundisplayed after all the events in the trace have been processed, by
268*4882a593Smuzhiyuncalling the print_syscall_totals() function from the trace_end()
269*4882a593Smuzhiyunhandler called at the end of script processing.
270*4882a593Smuzhiyun
271*4882a593SmuzhiyunThe final script producing the output shown above is shown in its
272*4882a593Smuzhiyunentirety below (syscall_name() helper is not yet available, you can
273*4882a593Smuzhiyunonly deal with id's for now):
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun----
276*4882a593Smuzhiyunimport os
277*4882a593Smuzhiyunimport sys
278*4882a593Smuzhiyun
279*4882a593Smuzhiyunsys.path.append(os.environ['PERF_EXEC_PATH'] + \
280*4882a593Smuzhiyun	'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
281*4882a593Smuzhiyun
282*4882a593Smuzhiyunfrom perf_trace_context import *
283*4882a593Smuzhiyunfrom Core import *
284*4882a593Smuzhiyunfrom Util import *
285*4882a593Smuzhiyun
286*4882a593Smuzhiyunsyscalls = autodict()
287*4882a593Smuzhiyun
288*4882a593Smuzhiyundef trace_end():
289*4882a593Smuzhiyun	print_syscall_totals()
290*4882a593Smuzhiyun
291*4882a593Smuzhiyundef raw_syscalls__sys_enter(event_name, context, common_cpu,
292*4882a593Smuzhiyun	common_secs, common_nsecs, common_pid, common_comm,
293*4882a593Smuzhiyun	id, args):
294*4882a593Smuzhiyun	try:
295*4882a593Smuzhiyun		syscalls[id] += 1
296*4882a593Smuzhiyun	except TypeError:
297*4882a593Smuzhiyun		syscalls[id] = 1
298*4882a593Smuzhiyun
299*4882a593Smuzhiyundef print_syscall_totals():
300*4882a593Smuzhiyun    if for_comm is not None:
301*4882a593Smuzhiyun	    print "\nsyscall events for %s:\n\n" % (for_comm),
302*4882a593Smuzhiyun    else:
303*4882a593Smuzhiyun	    print "\nsyscall events:\n\n",
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun    print "%-40s  %10s\n" % ("event", "count"),
306*4882a593Smuzhiyun    print "%-40s  %10s\n" % ("----------------------------------------", \
307*4882a593Smuzhiyun                                 "-----------"),
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun    for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
310*4882a593Smuzhiyun				  reverse = True):
311*4882a593Smuzhiyun	    print "%-40s  %10d\n" % (syscall_name(id), val),
312*4882a593Smuzhiyun----
313*4882a593Smuzhiyun
314*4882a593SmuzhiyunThe script can be run just as before:
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun  # perf script -s syscall-counts.py
317*4882a593Smuzhiyun
318*4882a593SmuzhiyunSo those are the essential steps in writing and running a script.  The
319*4882a593Smuzhiyunprocess can be generalized to any tracepoint or set of tracepoints
320*4882a593Smuzhiyunyou're interested in - basically find the tracepoint(s) you're
321*4882a593Smuzhiyuninterested in by looking at the list of available events shown by
322*4882a593Smuzhiyun'perf list' and/or look in /sys/kernel/debug/tracing/events/ for
323*4882a593Smuzhiyundetailed event and field info, record the corresponding trace data
324*4882a593Smuzhiyunusing 'perf record', passing it the list of interesting events,
325*4882a593Smuzhiyungenerate a skeleton script using 'perf script -g python' and modify the
326*4882a593Smuzhiyuncode to aggregate and display it for your particular needs.
327*4882a593Smuzhiyun
328*4882a593SmuzhiyunAfter you've done that you may end up with a general-purpose script
329*4882a593Smuzhiyunthat you want to keep around and have available for future use.  By
330*4882a593Smuzhiyunwriting a couple of very simple shell scripts and putting them in the
331*4882a593Smuzhiyunright place, you can have your script listed alongside the other
332*4882a593Smuzhiyunscripts listed by the 'perf script -l' command e.g.:
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun----
335*4882a593Smuzhiyun# perf script -l
336*4882a593SmuzhiyunList of available trace scripts:
337*4882a593Smuzhiyun  wakeup-latency                       system-wide min/max/avg wakeup latency
338*4882a593Smuzhiyun  rw-by-file <comm>                    r/w activity for a program, by file
339*4882a593Smuzhiyun  rw-by-pid                            system-wide r/w activity
340*4882a593Smuzhiyun----
341*4882a593Smuzhiyun
342*4882a593SmuzhiyunA nice side effect of doing this is that you also then capture the
343*4882a593Smuzhiyunprobably lengthy 'perf record' command needed to record the events for
344*4882a593Smuzhiyunthe script.
345*4882a593Smuzhiyun
346*4882a593SmuzhiyunTo have the script appear as a 'built-in' script, you write two simple
347*4882a593Smuzhiyunscripts, one for recording and one for 'reporting'.
348*4882a593Smuzhiyun
349*4882a593SmuzhiyunThe 'record' script is a shell script with the same base name as your
350*4882a593Smuzhiyunscript, but with -record appended.  The shell script should be put
351*4882a593Smuzhiyuninto the perf/scripts/python/bin directory in the kernel source tree.
352*4882a593SmuzhiyunIn that script, you write the 'perf record' command-line needed for
353*4882a593Smuzhiyunyour script:
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun----
356*4882a593Smuzhiyun# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-record
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun#!/bin/bash
359*4882a593Smuzhiyunperf record -a -e raw_syscalls:sys_enter
360*4882a593Smuzhiyun----
361*4882a593Smuzhiyun
362*4882a593SmuzhiyunThe 'report' script is also a shell script with the same base name as
363*4882a593Smuzhiyunyour script, but with -report appended.  It should also be located in
364*4882a593Smuzhiyunthe perf/scripts/python/bin directory.  In that script, you write the
365*4882a593Smuzhiyun'perf script -s' command-line needed for running your script:
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun----
368*4882a593Smuzhiyun# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun#!/bin/bash
371*4882a593Smuzhiyun# description: system-wide syscall counts
372*4882a593Smuzhiyunperf script -s ~/libexec/perf-core/scripts/python/syscall-counts.py
373*4882a593Smuzhiyun----
374*4882a593Smuzhiyun
375*4882a593SmuzhiyunNote that the location of the Python script given in the shell script
376*4882a593Smuzhiyunis in the libexec/perf-core/scripts/python directory - this is where
377*4882a593Smuzhiyunthe script will be copied by 'make install' when you install perf.
378*4882a593SmuzhiyunFor the installation to install your script there, your script needs
379*4882a593Smuzhiyunto be located in the perf/scripts/python directory in the kernel
380*4882a593Smuzhiyunsource tree:
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun----
383*4882a593Smuzhiyun# ls -al kernel-source/tools/perf/scripts/python
384*4882a593Smuzhiyuntotal 32
385*4882a593Smuzhiyundrwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
386*4882a593Smuzhiyundrwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
387*4882a593Smuzhiyundrwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin
388*4882a593Smuzhiyun-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py
389*4882a593Smuzhiyundrwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util
390*4882a593Smuzhiyun-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py
391*4882a593Smuzhiyun----
392*4882a593Smuzhiyun
393*4882a593SmuzhiyunOnce you've done that (don't forget to do a new 'make install',
394*4882a593Smuzhiyunotherwise your script won't show up at run-time), 'perf script -l'
395*4882a593Smuzhiyunshould show a new entry for your script:
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun----
398*4882a593Smuzhiyun# perf script -l
399*4882a593SmuzhiyunList of available trace scripts:
400*4882a593Smuzhiyun  wakeup-latency                       system-wide min/max/avg wakeup latency
401*4882a593Smuzhiyun  rw-by-file <comm>                    r/w activity for a program, by file
402*4882a593Smuzhiyun  rw-by-pid                            system-wide r/w activity
403*4882a593Smuzhiyun  syscall-counts                       system-wide syscall counts
404*4882a593Smuzhiyun----
405*4882a593Smuzhiyun
406*4882a593SmuzhiyunYou can now perform the record step via 'perf script record':
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun  # perf script record syscall-counts
409*4882a593Smuzhiyun
410*4882a593Smuzhiyunand display the output using 'perf script report':
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun  # perf script report syscall-counts
413*4882a593Smuzhiyun
414*4882a593SmuzhiyunSTARTER SCRIPTS
415*4882a593Smuzhiyun---------------
416*4882a593Smuzhiyun
417*4882a593SmuzhiyunYou can quickly get started writing a script for a particular set of
418*4882a593Smuzhiyuntrace data by generating a skeleton script using 'perf script -g
419*4882a593Smuzhiyunpython' in the same directory as an existing perf.data trace file.
420*4882a593SmuzhiyunThat will generate a starter script containing a handler for each of
421*4882a593Smuzhiyunthe event types in the trace file; it simply prints every available
422*4882a593Smuzhiyunfield for each event in the trace file.
423*4882a593Smuzhiyun
424*4882a593SmuzhiyunYou can also look at the existing scripts in
425*4882a593Smuzhiyun~/libexec/perf-core/scripts/python for typical examples showing how to
426*4882a593Smuzhiyundo basic things like aggregate event data, print results, etc.  Also,
427*4882a593Smuzhiyunthe check-perf-script.py script, while not interesting for its results,
428*4882a593Smuzhiyunattempts to exercise all of the main scripting features.
429*4882a593Smuzhiyun
430*4882a593SmuzhiyunEVENT HANDLERS
431*4882a593Smuzhiyun--------------
432*4882a593Smuzhiyun
433*4882a593SmuzhiyunWhen perf script is invoked using a trace script, a user-defined
434*4882a593Smuzhiyun'handler function' is called for each event in the trace.  If there's
435*4882a593Smuzhiyunno handler function defined for a given event type, the event is
436*4882a593Smuzhiyunignored (or passed to a 'trace_unhandled' function, see below) and the
437*4882a593Smuzhiyunnext event is processed.
438*4882a593Smuzhiyun
439*4882a593SmuzhiyunMost of the event's field values are passed as arguments to the
440*4882a593Smuzhiyunhandler function; some of the less common ones aren't - those are
441*4882a593Smuzhiyunavailable as calls back into the perf executable (see below).
442*4882a593Smuzhiyun
443*4882a593SmuzhiyunAs an example, the following perf record command can be used to record
444*4882a593Smuzhiyunall sched_wakeup events in the system:
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun # perf record -a -e sched:sched_wakeup
447*4882a593Smuzhiyun
448*4882a593SmuzhiyunTraces meant to be processed using a script should be recorded with
449*4882a593Smuzhiyunthe above option: -a to enable system-wide collection.
450*4882a593Smuzhiyun
451*4882a593SmuzhiyunThe format file for the sched_wakep event defines the following fields
452*4882a593Smuzhiyun(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format):
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun----
455*4882a593Smuzhiyun format:
456*4882a593Smuzhiyun        field:unsigned short common_type;
457*4882a593Smuzhiyun        field:unsigned char common_flags;
458*4882a593Smuzhiyun        field:unsigned char common_preempt_count;
459*4882a593Smuzhiyun        field:int common_pid;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun        field:char comm[TASK_COMM_LEN];
462*4882a593Smuzhiyun        field:pid_t pid;
463*4882a593Smuzhiyun        field:int prio;
464*4882a593Smuzhiyun        field:int success;
465*4882a593Smuzhiyun        field:int target_cpu;
466*4882a593Smuzhiyun----
467*4882a593Smuzhiyun
468*4882a593SmuzhiyunThe handler function for this event would be defined as:
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun----
471*4882a593Smuzhiyundef sched__sched_wakeup(event_name, context, common_cpu, common_secs,
472*4882a593Smuzhiyun       common_nsecs, common_pid, common_comm,
473*4882a593Smuzhiyun       comm, pid, prio, success, target_cpu):
474*4882a593Smuzhiyun       pass
475*4882a593Smuzhiyun----
476*4882a593Smuzhiyun
477*4882a593SmuzhiyunThe handler function takes the form subsystem__event_name.
478*4882a593Smuzhiyun
479*4882a593SmuzhiyunThe common_* arguments in the handler's argument list are the set of
480*4882a593Smuzhiyunarguments passed to all event handlers; some of the fields correspond
481*4882a593Smuzhiyunto the common_* fields in the format file, but some are synthesized,
482*4882a593Smuzhiyunand some of the common_* fields aren't common enough to to be passed
483*4882a593Smuzhiyunto every event as arguments but are available as library functions.
484*4882a593Smuzhiyun
485*4882a593SmuzhiyunHere's a brief description of each of the invariant event args:
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun event_name 	  	    the name of the event as text
488*4882a593Smuzhiyun context		    an opaque 'cookie' used in calls back into perf
489*4882a593Smuzhiyun common_cpu		    the cpu the event occurred on
490*4882a593Smuzhiyun common_secs		    the secs portion of the event timestamp
491*4882a593Smuzhiyun common_nsecs		    the nsecs portion of the event timestamp
492*4882a593Smuzhiyun common_pid		    the pid of the current task
493*4882a593Smuzhiyun common_comm		    the name of the current process
494*4882a593Smuzhiyun
495*4882a593SmuzhiyunAll of the remaining fields in the event's format file have
496*4882a593Smuzhiyuncounterparts as handler function arguments of the same name, as can be
497*4882a593Smuzhiyunseen in the example above.
498*4882a593Smuzhiyun
499*4882a593SmuzhiyunThe above provides the basics needed to directly access every field of
500*4882a593Smuzhiyunevery event in a trace, which covers 90% of what you need to know to
501*4882a593Smuzhiyunwrite a useful trace script.  The sections below cover the rest.
502*4882a593Smuzhiyun
503*4882a593SmuzhiyunSCRIPT LAYOUT
504*4882a593Smuzhiyun-------------
505*4882a593Smuzhiyun
506*4882a593SmuzhiyunEvery perf script Python script should start by setting up a Python
507*4882a593Smuzhiyunmodule search path and 'import'ing a few support modules (see module
508*4882a593Smuzhiyundescriptions below):
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun----
511*4882a593Smuzhiyun import os
512*4882a593Smuzhiyun import sys
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun sys.path.append(os.environ['PERF_EXEC_PATH'] + \
515*4882a593Smuzhiyun	      '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun from perf_trace_context import *
518*4882a593Smuzhiyun from Core import *
519*4882a593Smuzhiyun----
520*4882a593Smuzhiyun
521*4882a593SmuzhiyunThe rest of the script can contain handler functions and support
522*4882a593Smuzhiyunfunctions in any order.
523*4882a593Smuzhiyun
524*4882a593SmuzhiyunAside from the event handler functions discussed above, every script
525*4882a593Smuzhiyuncan implement a set of optional functions:
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun*trace_begin*, if defined, is called before any event is processed and
528*4882a593Smuzhiyungives scripts a chance to do setup tasks:
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun----
531*4882a593Smuzhiyundef trace_begin():
532*4882a593Smuzhiyun    pass
533*4882a593Smuzhiyun----
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun*trace_end*, if defined, is called after all events have been
536*4882a593Smuzhiyun processed and gives scripts a chance to do end-of-script tasks, such
537*4882a593Smuzhiyun as display results:
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun----
540*4882a593Smuzhiyundef trace_end():
541*4882a593Smuzhiyun    pass
542*4882a593Smuzhiyun----
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun*trace_unhandled*, if defined, is called after for any event that
545*4882a593Smuzhiyun doesn't have a handler explicitly defined for it.  The standard set
546*4882a593Smuzhiyun of common arguments are passed into it:
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun----
549*4882a593Smuzhiyundef trace_unhandled(event_name, context, event_fields_dict):
550*4882a593Smuzhiyun    pass
551*4882a593Smuzhiyun----
552*4882a593Smuzhiyun
553*4882a593SmuzhiyunThe remaining sections provide descriptions of each of the available
554*4882a593Smuzhiyunbuilt-in perf script Python modules and their associated functions.
555*4882a593Smuzhiyun
556*4882a593SmuzhiyunAVAILABLE MODULES AND FUNCTIONS
557*4882a593Smuzhiyun-------------------------------
558*4882a593Smuzhiyun
559*4882a593SmuzhiyunThe following sections describe the functions and variables available
560*4882a593Smuzhiyunvia the various perf script Python modules.  To use the functions and
561*4882a593Smuzhiyunvariables from the given module, add the corresponding 'from XXXX
562*4882a593Smuzhiyunimport' line to your perf script script.
563*4882a593Smuzhiyun
564*4882a593SmuzhiyunCore.py Module
565*4882a593Smuzhiyun~~~~~~~~~~~~~~
566*4882a593Smuzhiyun
567*4882a593SmuzhiyunThese functions provide some essential functions to user scripts.
568*4882a593Smuzhiyun
569*4882a593SmuzhiyunThe *flag_str* and *symbol_str* functions provide human-readable
570*4882a593Smuzhiyunstrings for flag and symbolic fields.  These correspond to the strings
571*4882a593Smuzhiyunand values parsed from the 'print fmt' fields of the event format
572*4882a593Smuzhiyunfiles:
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun  flag_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the flag field field_name of event event_name
575*4882a593Smuzhiyun  symbol_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the symbolic field field_name of event event_name
576*4882a593Smuzhiyun
577*4882a593SmuzhiyunThe *autodict* function returns a special kind of Python
578*4882a593Smuzhiyundictionary that implements Perl's 'autovivifying' hashes in Python
579*4882a593Smuzhiyuni.e. with autovivifying hashes, you can assign nested hash values
580*4882a593Smuzhiyunwithout having to go to the trouble of creating intermediate levels if
581*4882a593Smuzhiyunthey don't exist.
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun  autodict() - returns an autovivifying dictionary instance
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun
586*4882a593Smuzhiyunperf_trace_context Module
587*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~~
588*4882a593Smuzhiyun
589*4882a593SmuzhiyunSome of the 'common' fields in the event format file aren't all that
590*4882a593Smuzhiyuncommon, but need to be made accessible to user scripts nonetheless.
591*4882a593Smuzhiyun
592*4882a593Smuzhiyunperf_trace_context defines a set of functions that can be used to
593*4882a593Smuzhiyunaccess this data in the context of the current event.  Each of these
594*4882a593Smuzhiyunfunctions expects a context variable, which is the same as the
595*4882a593Smuzhiyuncontext variable passed into every event handler as the second
596*4882a593Smuzhiyunargument.
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun common_pc(context) - returns common_preempt count for the current event
599*4882a593Smuzhiyun common_flags(context) - returns common_flags for the current event
600*4882a593Smuzhiyun common_lock_depth(context) - returns common_lock_depth for the current event
601*4882a593Smuzhiyun
602*4882a593SmuzhiyunUtil.py Module
603*4882a593Smuzhiyun~~~~~~~~~~~~~~
604*4882a593Smuzhiyun
605*4882a593SmuzhiyunVarious utility functions for use with perf script:
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun  nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair
608*4882a593Smuzhiyun  nsecs_secs(nsecs) - returns whole secs portion given nsecs
609*4882a593Smuzhiyun  nsecs_nsecs(nsecs) - returns nsecs remainder given nsecs
610*4882a593Smuzhiyun  nsecs_str(nsecs) - returns printable string in the form secs.nsecs
611*4882a593Smuzhiyun  avg(total, n) - returns average given a sum and a total number of values
612*4882a593Smuzhiyun
613*4882a593SmuzhiyunSUPPORTED FIELDS
614*4882a593Smuzhiyun----------------
615*4882a593Smuzhiyun
616*4882a593SmuzhiyunCurrently supported fields:
617*4882a593Smuzhiyun
618*4882a593Smuzhiyunev_name, comm, pid, tid, cpu, ip, time, period, phys_addr, addr,
619*4882a593Smuzhiyunsymbol, dso, time_enabled, time_running, values, callchain,
620*4882a593Smuzhiyunbrstack, brstacksym, datasrc, datasrc_decode, iregs, uregs,
621*4882a593Smuzhiyunweight, transaction, raw_buf, attr.
622*4882a593Smuzhiyun
623*4882a593SmuzhiyunSome fields have sub items:
624*4882a593Smuzhiyun
625*4882a593Smuzhiyunbrstack:
626*4882a593Smuzhiyun    from, to, from_dsoname, to_dsoname, mispred,
627*4882a593Smuzhiyun    predicted, in_tx, abort, cycles.
628*4882a593Smuzhiyun
629*4882a593Smuzhiyunbrstacksym:
630*4882a593Smuzhiyun    items: from, to, pred, in_tx, abort (converted string)
631*4882a593Smuzhiyun
632*4882a593SmuzhiyunFor example,
633*4882a593SmuzhiyunWe can use this code to print brstack "from", "to", "cycles".
634*4882a593Smuzhiyun
635*4882a593Smuzhiyunif 'brstack' in dict:
636*4882a593Smuzhiyun	for entry in dict['brstack']:
637*4882a593Smuzhiyun		print "from %s, to %s, cycles %s" % (entry["from"], entry["to"], entry["cycles"])
638*4882a593Smuzhiyun
639*4882a593SmuzhiyunSEE ALSO
640*4882a593Smuzhiyun--------
641*4882a593Smuzhiyunlinkperf:perf-script[1]
642