18c2ecf20Sopenharmony_ciperf-script-python(1) 28c2ecf20Sopenharmony_ci==================== 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ciNAME 58c2ecf20Sopenharmony_ci---- 68c2ecf20Sopenharmony_ciperf-script-python - Process trace data with a Python script 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ciSYNOPSIS 98c2ecf20Sopenharmony_ci-------- 108c2ecf20Sopenharmony_ci[verse] 118c2ecf20Sopenharmony_ci'perf script' [-s [Python]:script[.py] ] 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciDESCRIPTION 148c2ecf20Sopenharmony_ci----------- 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciThis perf script option is used to process perf script data using perf's 178c2ecf20Sopenharmony_cibuilt-in Python interpreter. It reads and processes the input file and 188c2ecf20Sopenharmony_cidisplays the results of the trace analysis implemented in the given 198c2ecf20Sopenharmony_ciPython script, if any. 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciA QUICK EXAMPLE 228c2ecf20Sopenharmony_ci--------------- 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciThis section shows the process, start to finish, of creating a working 258c2ecf20Sopenharmony_ciPython script that aggregates and extracts useful information from a 268c2ecf20Sopenharmony_ciraw perf script stream. You can avoid reading the rest of this 278c2ecf20Sopenharmony_cidocument if an example is enough for you; the rest of the document 288c2ecf20Sopenharmony_ciprovides more details on each step and lists the library functions 298c2ecf20Sopenharmony_ciavailable to script writers. 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciThis example actually details the steps that were used to create the 328c2ecf20Sopenharmony_ci'syscall-counts' script you see when you list the available perf script 338c2ecf20Sopenharmony_ciscripts via 'perf script -l'. As such, this script also shows how to 348c2ecf20Sopenharmony_ciintegrate your script into the list of general-purpose 'perf script' 358c2ecf20Sopenharmony_ciscripts listed by that command. 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciThe syscall-counts script is a simple script, but demonstrates all the 388c2ecf20Sopenharmony_cibasic ideas necessary to create a useful script. Here's an example 398c2ecf20Sopenharmony_ciof its output (syscall names are not yet supported, they will appear 408c2ecf20Sopenharmony_cias numbers): 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci---- 438c2ecf20Sopenharmony_cisyscall events: 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cievent count 468c2ecf20Sopenharmony_ci---------------------------------------- ----------- 478c2ecf20Sopenharmony_cisys_write 455067 488c2ecf20Sopenharmony_cisys_getdents 4072 498c2ecf20Sopenharmony_cisys_close 3037 508c2ecf20Sopenharmony_cisys_swapoff 1769 518c2ecf20Sopenharmony_cisys_read 923 528c2ecf20Sopenharmony_cisys_sched_setparam 826 538c2ecf20Sopenharmony_cisys_open 331 548c2ecf20Sopenharmony_cisys_newfstat 326 558c2ecf20Sopenharmony_cisys_mmap 217 568c2ecf20Sopenharmony_cisys_munmap 216 578c2ecf20Sopenharmony_cisys_futex 141 588c2ecf20Sopenharmony_cisys_select 102 598c2ecf20Sopenharmony_cisys_poll 84 608c2ecf20Sopenharmony_cisys_setitimer 12 618c2ecf20Sopenharmony_cisys_writev 8 628c2ecf20Sopenharmony_ci15 8 638c2ecf20Sopenharmony_cisys_lseek 7 648c2ecf20Sopenharmony_cisys_rt_sigprocmask 6 658c2ecf20Sopenharmony_cisys_wait4 3 668c2ecf20Sopenharmony_cisys_ioctl 3 678c2ecf20Sopenharmony_cisys_set_robust_list 1 688c2ecf20Sopenharmony_cisys_exit 1 698c2ecf20Sopenharmony_ci56 1 708c2ecf20Sopenharmony_cisys_access 1 718c2ecf20Sopenharmony_ci---- 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciBasically our task is to keep a per-syscall tally that gets updated 748c2ecf20Sopenharmony_cievery time a system call occurs in the system. Our script will do 758c2ecf20Sopenharmony_cithat, but first we need to record the data that will be processed by 768c2ecf20Sopenharmony_cithat script. Theoretically, there are a couple of ways we could do 778c2ecf20Sopenharmony_cithat: 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci- we could enable every event under the tracing/events/syscalls 808c2ecf20Sopenharmony_ci directory, but this is over 600 syscalls, well beyond the number 818c2ecf20Sopenharmony_ci allowable by perf. These individual syscall events will however be 828c2ecf20Sopenharmony_ci useful if we want to later use the guidance we get from the 838c2ecf20Sopenharmony_ci general-purpose scripts to drill down and get more detail about 848c2ecf20Sopenharmony_ci individual syscalls of interest. 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci- we can enable the sys_enter and/or sys_exit syscalls found under 878c2ecf20Sopenharmony_ci tracing/events/raw_syscalls. These are called for all syscalls; the 888c2ecf20Sopenharmony_ci 'id' field can be used to distinguish between individual syscall 898c2ecf20Sopenharmony_ci numbers. 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciFor this script, we only need to know that a syscall was entered; we 928c2ecf20Sopenharmony_cidon't care how it exited, so we'll use 'perf record' to record only 938c2ecf20Sopenharmony_cithe sys_enter events: 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci---- 968c2ecf20Sopenharmony_ci# perf record -a -e raw_syscalls:sys_enter 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci^C[ perf record: Woken up 1 times to write data ] 998c2ecf20Sopenharmony_ci[ perf record: Captured and wrote 56.545 MB perf.data (~2470503 samples) ] 1008c2ecf20Sopenharmony_ci---- 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciThe options basically say to collect data for every syscall event 1038c2ecf20Sopenharmony_cisystem-wide and multiplex the per-cpu output into a single stream. 1048c2ecf20Sopenharmony_ciThat single stream will be recorded in a file in the current directory 1058c2ecf20Sopenharmony_cicalled perf.data. 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciOnce we have a perf.data file containing our data, we can use the -g 1088c2ecf20Sopenharmony_ci'perf script' option to generate a Python script that will contain a 1098c2ecf20Sopenharmony_cicallback handler for each event type found in the perf.data trace 1108c2ecf20Sopenharmony_cistream (for more details, see the STARTER SCRIPTS section). 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci---- 1138c2ecf20Sopenharmony_ci# perf script -g python 1148c2ecf20Sopenharmony_cigenerated Python script: perf-script.py 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciThe output file created also in the current directory is named 1178c2ecf20Sopenharmony_ciperf-script.py. Here's the file in its entirety: 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci# perf script event handlers, generated by perf script -g python 1208c2ecf20Sopenharmony_ci# Licensed under the terms of the GNU GPL License version 2 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci# The common_* event handler fields are the most useful fields common to 1238c2ecf20Sopenharmony_ci# all events. They don't necessarily correspond to the 'common_*' fields 1248c2ecf20Sopenharmony_ci# in the format files. Those fields not available as handler params can 1258c2ecf20Sopenharmony_ci# be retrieved using Python functions of the form common_*(context). 1268c2ecf20Sopenharmony_ci# See the perf-script-python Documentation for the list of available functions. 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ciimport os 1298c2ecf20Sopenharmony_ciimport sys 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cisys.path.append(os.environ['PERF_EXEC_PATH'] + \ 1328c2ecf20Sopenharmony_ci '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cifrom perf_trace_context import * 1358c2ecf20Sopenharmony_cifrom Core import * 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cidef trace_begin(): 1388c2ecf20Sopenharmony_ci print "in trace_begin" 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cidef trace_end(): 1418c2ecf20Sopenharmony_ci print "in trace_end" 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cidef raw_syscalls__sys_enter(event_name, context, common_cpu, 1448c2ecf20Sopenharmony_ci common_secs, common_nsecs, common_pid, common_comm, 1458c2ecf20Sopenharmony_ci id, args): 1468c2ecf20Sopenharmony_ci print_header(event_name, common_cpu, common_secs, common_nsecs, 1478c2ecf20Sopenharmony_ci common_pid, common_comm) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci print "id=%d, args=%s\n" % \ 1508c2ecf20Sopenharmony_ci (id, args), 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cidef trace_unhandled(event_name, context, event_fields_dict): 1538c2ecf20Sopenharmony_ci print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cidef print_header(event_name, cpu, secs, nsecs, pid, comm): 1568c2ecf20Sopenharmony_ci print "%-20s %5u %05u.%09u %8u %-20s " % \ 1578c2ecf20Sopenharmony_ci (event_name, cpu, secs, nsecs, pid, comm), 1588c2ecf20Sopenharmony_ci---- 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ciAt the top is a comment block followed by some import statements and a 1618c2ecf20Sopenharmony_cipath append which every perf script script should include. 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ciFollowing that are a couple generated functions, trace_begin() and 1648c2ecf20Sopenharmony_citrace_end(), which are called at the beginning and the end of the 1658c2ecf20Sopenharmony_ciscript respectively (for more details, see the SCRIPT_LAYOUT section 1668c2ecf20Sopenharmony_cibelow). 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciFollowing those are the 'event handler' functions generated one for 1698c2ecf20Sopenharmony_cievery event in the 'perf record' output. The handler functions take 1708c2ecf20Sopenharmony_cithe form subsystem__event_name, and contain named parameters, one for 1718c2ecf20Sopenharmony_cieach field in the event; in this case, there's only one event, 1728c2ecf20Sopenharmony_ciraw_syscalls__sys_enter(). (see the EVENT HANDLERS section below for 1738c2ecf20Sopenharmony_cimore info on event handlers). 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ciThe final couple of functions are, like the begin and end functions, 1768c2ecf20Sopenharmony_cigenerated for every script. The first, trace_unhandled(), is called 1778c2ecf20Sopenharmony_cievery time the script finds an event in the perf.data file that 1788c2ecf20Sopenharmony_cidoesn't correspond to any event handler in the script. This could 1798c2ecf20Sopenharmony_cimean either that the record step recorded event types that it wasn't 1808c2ecf20Sopenharmony_cireally interested in, or the script was run against a trace file that 1818c2ecf20Sopenharmony_cidoesn't correspond to the script. 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciThe script generated by -g option simply prints a line for each 1848c2ecf20Sopenharmony_cievent found in the trace stream i.e. it basically just dumps the event 1858c2ecf20Sopenharmony_ciand its parameter values to stdout. The print_header() function is 1868c2ecf20Sopenharmony_cisimply a utility function used for that purpose. Let's rename the 1878c2ecf20Sopenharmony_ciscript and run it to see the default output: 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci---- 1908c2ecf20Sopenharmony_ci# mv perf-script.py syscall-counts.py 1918c2ecf20Sopenharmony_ci# perf script -s syscall-counts.py 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847582083 7506 perf id=1, args= 1948c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847595764 7506 perf id=1, args= 1958c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847620860 7506 perf id=1, args= 1968c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847710478 6533 npviewer.bin id=78, args= 1978c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847719204 6533 npviewer.bin id=142, args= 1988c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847755445 6533 npviewer.bin id=3, args= 1998c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847775601 6533 npviewer.bin id=3, args= 2008c2ecf20Sopenharmony_ciraw_syscalls__sys_enter 1 00840.847781820 6533 npviewer.bin id=3, args= 2018c2ecf20Sopenharmony_ci. 2028c2ecf20Sopenharmony_ci. 2038c2ecf20Sopenharmony_ci. 2048c2ecf20Sopenharmony_ci---- 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ciOf course, for this script, we're not interested in printing every 2078c2ecf20Sopenharmony_citrace event, but rather aggregating it in a useful way. So we'll get 2088c2ecf20Sopenharmony_cirid of everything to do with printing as well as the trace_begin() and 2098c2ecf20Sopenharmony_citrace_unhandled() functions, which we won't be using. That leaves us 2108c2ecf20Sopenharmony_ciwith this minimalistic skeleton: 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci---- 2138c2ecf20Sopenharmony_ciimport os 2148c2ecf20Sopenharmony_ciimport sys 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cisys.path.append(os.environ['PERF_EXEC_PATH'] + \ 2178c2ecf20Sopenharmony_ci '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cifrom perf_trace_context import * 2208c2ecf20Sopenharmony_cifrom Core import * 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cidef trace_end(): 2238c2ecf20Sopenharmony_ci print "in trace_end" 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cidef raw_syscalls__sys_enter(event_name, context, common_cpu, 2268c2ecf20Sopenharmony_ci common_secs, common_nsecs, common_pid, common_comm, 2278c2ecf20Sopenharmony_ci id, args): 2288c2ecf20Sopenharmony_ci---- 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ciIn trace_end(), we'll simply print the results, but first we need to 2318c2ecf20Sopenharmony_cigenerate some results to print. To do that we need to have our 2328c2ecf20Sopenharmony_cisys_enter() handler do the necessary tallying until all events have 2338c2ecf20Sopenharmony_cibeen counted. A hash table indexed by syscall id is a good way to 2348c2ecf20Sopenharmony_cistore that information; every time the sys_enter() handler is called, 2358c2ecf20Sopenharmony_ciwe simply increment a count associated with that hash entry indexed by 2368c2ecf20Sopenharmony_cithat syscall id: 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci---- 2398c2ecf20Sopenharmony_ci syscalls = autodict() 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci try: 2428c2ecf20Sopenharmony_ci syscalls[id] += 1 2438c2ecf20Sopenharmony_ci except TypeError: 2448c2ecf20Sopenharmony_ci syscalls[id] = 1 2458c2ecf20Sopenharmony_ci---- 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ciThe syscalls 'autodict' object is a special kind of Python dictionary 2488c2ecf20Sopenharmony_ci(implemented in Core.py) that implements Perl's 'autovivifying' hashes 2498c2ecf20Sopenharmony_ciin Python i.e. with autovivifying hashes, you can assign nested hash 2508c2ecf20Sopenharmony_civalues without having to go to the trouble of creating intermediate 2518c2ecf20Sopenharmony_cilevels if they don't exist e.g syscalls[comm][pid][id] = 1 will create 2528c2ecf20Sopenharmony_cithe intermediate hash levels and finally assign the value 1 to the 2538c2ecf20Sopenharmony_cihash entry for 'id' (because the value being assigned isn't a hash 2548c2ecf20Sopenharmony_ciobject itself, the initial value is assigned in the TypeError 2558c2ecf20Sopenharmony_ciexception. Well, there may be a better way to do this in Python but 2568c2ecf20Sopenharmony_cithat's what works for now). 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciPutting that code into the raw_syscalls__sys_enter() handler, we 2598c2ecf20Sopenharmony_cieffectively end up with a single-level dictionary keyed on syscall id 2608c2ecf20Sopenharmony_ciand having the counts we've tallied as values. 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ciThe print_syscall_totals() function iterates over the entries in the 2638c2ecf20Sopenharmony_cidictionary and displays a line for each entry containing the syscall 2648c2ecf20Sopenharmony_ciname (the dictionary keys contain the syscall ids, which are passed to 2658c2ecf20Sopenharmony_cithe Util function syscall_name(), which translates the raw syscall 2668c2ecf20Sopenharmony_cinumbers to the corresponding syscall name strings). The output is 2678c2ecf20Sopenharmony_cidisplayed after all the events in the trace have been processed, by 2688c2ecf20Sopenharmony_cicalling the print_syscall_totals() function from the trace_end() 2698c2ecf20Sopenharmony_cihandler called at the end of script processing. 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciThe final script producing the output shown above is shown in its 2728c2ecf20Sopenharmony_cientirety below (syscall_name() helper is not yet available, you can 2738c2ecf20Sopenharmony_cionly deal with id's for now): 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci---- 2768c2ecf20Sopenharmony_ciimport os 2778c2ecf20Sopenharmony_ciimport sys 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cisys.path.append(os.environ['PERF_EXEC_PATH'] + \ 2808c2ecf20Sopenharmony_ci '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cifrom perf_trace_context import * 2838c2ecf20Sopenharmony_cifrom Core import * 2848c2ecf20Sopenharmony_cifrom Util import * 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cisyscalls = autodict() 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cidef trace_end(): 2898c2ecf20Sopenharmony_ci print_syscall_totals() 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cidef raw_syscalls__sys_enter(event_name, context, common_cpu, 2928c2ecf20Sopenharmony_ci common_secs, common_nsecs, common_pid, common_comm, 2938c2ecf20Sopenharmony_ci id, args): 2948c2ecf20Sopenharmony_ci try: 2958c2ecf20Sopenharmony_ci syscalls[id] += 1 2968c2ecf20Sopenharmony_ci except TypeError: 2978c2ecf20Sopenharmony_ci syscalls[id] = 1 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cidef print_syscall_totals(): 3008c2ecf20Sopenharmony_ci if for_comm is not None: 3018c2ecf20Sopenharmony_ci print "\nsyscall events for %s:\n\n" % (for_comm), 3028c2ecf20Sopenharmony_ci else: 3038c2ecf20Sopenharmony_ci print "\nsyscall events:\n\n", 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci print "%-40s %10s\n" % ("event", "count"), 3068c2ecf20Sopenharmony_ci print "%-40s %10s\n" % ("----------------------------------------", \ 3078c2ecf20Sopenharmony_ci "-----------"), 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ 3108c2ecf20Sopenharmony_ci reverse = True): 3118c2ecf20Sopenharmony_ci print "%-40s %10d\n" % (syscall_name(id), val), 3128c2ecf20Sopenharmony_ci---- 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ciThe script can be run just as before: 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci # perf script -s syscall-counts.py 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ciSo those are the essential steps in writing and running a script. The 3198c2ecf20Sopenharmony_ciprocess can be generalized to any tracepoint or set of tracepoints 3208c2ecf20Sopenharmony_ciyou're interested in - basically find the tracepoint(s) you're 3218c2ecf20Sopenharmony_ciinterested in by looking at the list of available events shown by 3228c2ecf20Sopenharmony_ci'perf list' and/or look in /sys/kernel/debug/tracing/events/ for 3238c2ecf20Sopenharmony_cidetailed event and field info, record the corresponding trace data 3248c2ecf20Sopenharmony_ciusing 'perf record', passing it the list of interesting events, 3258c2ecf20Sopenharmony_cigenerate a skeleton script using 'perf script -g python' and modify the 3268c2ecf20Sopenharmony_cicode to aggregate and display it for your particular needs. 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ciAfter you've done that you may end up with a general-purpose script 3298c2ecf20Sopenharmony_cithat you want to keep around and have available for future use. By 3308c2ecf20Sopenharmony_ciwriting a couple of very simple shell scripts and putting them in the 3318c2ecf20Sopenharmony_ciright place, you can have your script listed alongside the other 3328c2ecf20Sopenharmony_ciscripts listed by the 'perf script -l' command e.g.: 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci---- 3358c2ecf20Sopenharmony_ci# perf script -l 3368c2ecf20Sopenharmony_ciList of available trace scripts: 3378c2ecf20Sopenharmony_ci wakeup-latency system-wide min/max/avg wakeup latency 3388c2ecf20Sopenharmony_ci rw-by-file <comm> r/w activity for a program, by file 3398c2ecf20Sopenharmony_ci rw-by-pid system-wide r/w activity 3408c2ecf20Sopenharmony_ci---- 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ciA nice side effect of doing this is that you also then capture the 3438c2ecf20Sopenharmony_ciprobably lengthy 'perf record' command needed to record the events for 3448c2ecf20Sopenharmony_cithe script. 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ciTo have the script appear as a 'built-in' script, you write two simple 3478c2ecf20Sopenharmony_ciscripts, one for recording and one for 'reporting'. 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ciThe 'record' script is a shell script with the same base name as your 3508c2ecf20Sopenharmony_ciscript, but with -record appended. The shell script should be put 3518c2ecf20Sopenharmony_ciinto the perf/scripts/python/bin directory in the kernel source tree. 3528c2ecf20Sopenharmony_ciIn that script, you write the 'perf record' command-line needed for 3538c2ecf20Sopenharmony_ciyour script: 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci---- 3568c2ecf20Sopenharmony_ci# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-record 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci#!/bin/bash 3598c2ecf20Sopenharmony_ciperf record -a -e raw_syscalls:sys_enter 3608c2ecf20Sopenharmony_ci---- 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ciThe 'report' script is also a shell script with the same base name as 3638c2ecf20Sopenharmony_ciyour script, but with -report appended. It should also be located in 3648c2ecf20Sopenharmony_cithe perf/scripts/python/bin directory. In that script, you write the 3658c2ecf20Sopenharmony_ci'perf script -s' command-line needed for running your script: 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci---- 3688c2ecf20Sopenharmony_ci# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci#!/bin/bash 3718c2ecf20Sopenharmony_ci# description: system-wide syscall counts 3728c2ecf20Sopenharmony_ciperf script -s ~/libexec/perf-core/scripts/python/syscall-counts.py 3738c2ecf20Sopenharmony_ci---- 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ciNote that the location of the Python script given in the shell script 3768c2ecf20Sopenharmony_ciis in the libexec/perf-core/scripts/python directory - this is where 3778c2ecf20Sopenharmony_cithe script will be copied by 'make install' when you install perf. 3788c2ecf20Sopenharmony_ciFor the installation to install your script there, your script needs 3798c2ecf20Sopenharmony_cito be located in the perf/scripts/python directory in the kernel 3808c2ecf20Sopenharmony_cisource tree: 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci---- 3838c2ecf20Sopenharmony_ci# ls -al kernel-source/tools/perf/scripts/python 3848c2ecf20Sopenharmony_citotal 32 3858c2ecf20Sopenharmony_cidrwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . 3868c2ecf20Sopenharmony_cidrwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. 3878c2ecf20Sopenharmony_cidrwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin 3888c2ecf20Sopenharmony_ci-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py 3898c2ecf20Sopenharmony_cidrwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util 3908c2ecf20Sopenharmony_ci-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py 3918c2ecf20Sopenharmony_ci---- 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ciOnce you've done that (don't forget to do a new 'make install', 3948c2ecf20Sopenharmony_ciotherwise your script won't show up at run-time), 'perf script -l' 3958c2ecf20Sopenharmony_cishould show a new entry for your script: 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci---- 3988c2ecf20Sopenharmony_ci# perf script -l 3998c2ecf20Sopenharmony_ciList of available trace scripts: 4008c2ecf20Sopenharmony_ci wakeup-latency system-wide min/max/avg wakeup latency 4018c2ecf20Sopenharmony_ci rw-by-file <comm> r/w activity for a program, by file 4028c2ecf20Sopenharmony_ci rw-by-pid system-wide r/w activity 4038c2ecf20Sopenharmony_ci syscall-counts system-wide syscall counts 4048c2ecf20Sopenharmony_ci---- 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ciYou can now perform the record step via 'perf script record': 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci # perf script record syscall-counts 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ciand display the output using 'perf script report': 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci # perf script report syscall-counts 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ciSTARTER SCRIPTS 4158c2ecf20Sopenharmony_ci--------------- 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ciYou can quickly get started writing a script for a particular set of 4188c2ecf20Sopenharmony_citrace data by generating a skeleton script using 'perf script -g 4198c2ecf20Sopenharmony_cipython' in the same directory as an existing perf.data trace file. 4208c2ecf20Sopenharmony_ciThat will generate a starter script containing a handler for each of 4218c2ecf20Sopenharmony_cithe event types in the trace file; it simply prints every available 4228c2ecf20Sopenharmony_cifield for each event in the trace file. 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ciYou can also look at the existing scripts in 4258c2ecf20Sopenharmony_ci~/libexec/perf-core/scripts/python for typical examples showing how to 4268c2ecf20Sopenharmony_cido basic things like aggregate event data, print results, etc. Also, 4278c2ecf20Sopenharmony_cithe check-perf-script.py script, while not interesting for its results, 4288c2ecf20Sopenharmony_ciattempts to exercise all of the main scripting features. 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ciEVENT HANDLERS 4318c2ecf20Sopenharmony_ci-------------- 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ciWhen perf script is invoked using a trace script, a user-defined 4348c2ecf20Sopenharmony_ci'handler function' is called for each event in the trace. If there's 4358c2ecf20Sopenharmony_cino handler function defined for a given event type, the event is 4368c2ecf20Sopenharmony_ciignored (or passed to a 'trace_unhandled' function, see below) and the 4378c2ecf20Sopenharmony_cinext event is processed. 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ciMost of the event's field values are passed as arguments to the 4408c2ecf20Sopenharmony_cihandler function; some of the less common ones aren't - those are 4418c2ecf20Sopenharmony_ciavailable as calls back into the perf executable (see below). 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ciAs an example, the following perf record command can be used to record 4448c2ecf20Sopenharmony_ciall sched_wakeup events in the system: 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci # perf record -a -e sched:sched_wakeup 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ciTraces meant to be processed using a script should be recorded with 4498c2ecf20Sopenharmony_cithe above option: -a to enable system-wide collection. 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ciThe format file for the sched_wakep event defines the following fields 4528c2ecf20Sopenharmony_ci(see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci---- 4558c2ecf20Sopenharmony_ci format: 4568c2ecf20Sopenharmony_ci field:unsigned short common_type; 4578c2ecf20Sopenharmony_ci field:unsigned char common_flags; 4588c2ecf20Sopenharmony_ci field:unsigned char common_preempt_count; 4598c2ecf20Sopenharmony_ci field:int common_pid; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci field:char comm[TASK_COMM_LEN]; 4628c2ecf20Sopenharmony_ci field:pid_t pid; 4638c2ecf20Sopenharmony_ci field:int prio; 4648c2ecf20Sopenharmony_ci field:int success; 4658c2ecf20Sopenharmony_ci field:int target_cpu; 4668c2ecf20Sopenharmony_ci---- 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ciThe handler function for this event would be defined as: 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci---- 4718c2ecf20Sopenharmony_cidef sched__sched_wakeup(event_name, context, common_cpu, common_secs, 4728c2ecf20Sopenharmony_ci common_nsecs, common_pid, common_comm, 4738c2ecf20Sopenharmony_ci comm, pid, prio, success, target_cpu): 4748c2ecf20Sopenharmony_ci pass 4758c2ecf20Sopenharmony_ci---- 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ciThe handler function takes the form subsystem__event_name. 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ciThe common_* arguments in the handler's argument list are the set of 4808c2ecf20Sopenharmony_ciarguments passed to all event handlers; some of the fields correspond 4818c2ecf20Sopenharmony_cito the common_* fields in the format file, but some are synthesized, 4828c2ecf20Sopenharmony_ciand some of the common_* fields aren't common enough to to be passed 4838c2ecf20Sopenharmony_cito every event as arguments but are available as library functions. 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ciHere's a brief description of each of the invariant event args: 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci event_name the name of the event as text 4888c2ecf20Sopenharmony_ci context an opaque 'cookie' used in calls back into perf 4898c2ecf20Sopenharmony_ci common_cpu the cpu the event occurred on 4908c2ecf20Sopenharmony_ci common_secs the secs portion of the event timestamp 4918c2ecf20Sopenharmony_ci common_nsecs the nsecs portion of the event timestamp 4928c2ecf20Sopenharmony_ci common_pid the pid of the current task 4938c2ecf20Sopenharmony_ci common_comm the name of the current process 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ciAll of the remaining fields in the event's format file have 4968c2ecf20Sopenharmony_cicounterparts as handler function arguments of the same name, as can be 4978c2ecf20Sopenharmony_ciseen in the example above. 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ciThe above provides the basics needed to directly access every field of 5008c2ecf20Sopenharmony_cievery event in a trace, which covers 90% of what you need to know to 5018c2ecf20Sopenharmony_ciwrite a useful trace script. The sections below cover the rest. 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ciSCRIPT LAYOUT 5048c2ecf20Sopenharmony_ci------------- 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ciEvery perf script Python script should start by setting up a Python 5078c2ecf20Sopenharmony_cimodule search path and 'import'ing a few support modules (see module 5088c2ecf20Sopenharmony_cidescriptions below): 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci---- 5118c2ecf20Sopenharmony_ci import os 5128c2ecf20Sopenharmony_ci import sys 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 5158c2ecf20Sopenharmony_ci '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci from perf_trace_context import * 5188c2ecf20Sopenharmony_ci from Core import * 5198c2ecf20Sopenharmony_ci---- 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ciThe rest of the script can contain handler functions and support 5228c2ecf20Sopenharmony_cifunctions in any order. 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ciAside from the event handler functions discussed above, every script 5258c2ecf20Sopenharmony_cican implement a set of optional functions: 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci*trace_begin*, if defined, is called before any event is processed and 5288c2ecf20Sopenharmony_cigives scripts a chance to do setup tasks: 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci---- 5318c2ecf20Sopenharmony_cidef trace_begin(): 5328c2ecf20Sopenharmony_ci pass 5338c2ecf20Sopenharmony_ci---- 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci*trace_end*, if defined, is called after all events have been 5368c2ecf20Sopenharmony_ci processed and gives scripts a chance to do end-of-script tasks, such 5378c2ecf20Sopenharmony_ci as display results: 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci---- 5408c2ecf20Sopenharmony_cidef trace_end(): 5418c2ecf20Sopenharmony_ci pass 5428c2ecf20Sopenharmony_ci---- 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci*trace_unhandled*, if defined, is called after for any event that 5458c2ecf20Sopenharmony_ci doesn't have a handler explicitly defined for it. The standard set 5468c2ecf20Sopenharmony_ci of common arguments are passed into it: 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci---- 5498c2ecf20Sopenharmony_cidef trace_unhandled(event_name, context, event_fields_dict): 5508c2ecf20Sopenharmony_ci pass 5518c2ecf20Sopenharmony_ci---- 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ciThe remaining sections provide descriptions of each of the available 5548c2ecf20Sopenharmony_cibuilt-in perf script Python modules and their associated functions. 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ciAVAILABLE MODULES AND FUNCTIONS 5578c2ecf20Sopenharmony_ci------------------------------- 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ciThe following sections describe the functions and variables available 5608c2ecf20Sopenharmony_civia the various perf script Python modules. To use the functions and 5618c2ecf20Sopenharmony_civariables from the given module, add the corresponding 'from XXXX 5628c2ecf20Sopenharmony_ciimport' line to your perf script script. 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ciCore.py Module 5658c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~ 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ciThese functions provide some essential functions to user scripts. 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ciThe *flag_str* and *symbol_str* functions provide human-readable 5708c2ecf20Sopenharmony_cistrings for flag and symbolic fields. These correspond to the strings 5718c2ecf20Sopenharmony_ciand values parsed from the 'print fmt' fields of the event format 5728c2ecf20Sopenharmony_cifiles: 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci 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 5758c2ecf20Sopenharmony_ci 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 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ciThe *autodict* function returns a special kind of Python 5788c2ecf20Sopenharmony_cidictionary that implements Perl's 'autovivifying' hashes in Python 5798c2ecf20Sopenharmony_cii.e. with autovivifying hashes, you can assign nested hash values 5808c2ecf20Sopenharmony_ciwithout having to go to the trouble of creating intermediate levels if 5818c2ecf20Sopenharmony_cithey don't exist. 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci autodict() - returns an autovivifying dictionary instance 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ciperf_trace_context Module 5878c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~ 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ciSome of the 'common' fields in the event format file aren't all that 5908c2ecf20Sopenharmony_cicommon, but need to be made accessible to user scripts nonetheless. 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ciperf_trace_context defines a set of functions that can be used to 5938c2ecf20Sopenharmony_ciaccess this data in the context of the current event. Each of these 5948c2ecf20Sopenharmony_cifunctions expects a context variable, which is the same as the 5958c2ecf20Sopenharmony_cicontext variable passed into every event handler as the second 5968c2ecf20Sopenharmony_ciargument. 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci common_pc(context) - returns common_preempt count for the current event 5998c2ecf20Sopenharmony_ci common_flags(context) - returns common_flags for the current event 6008c2ecf20Sopenharmony_ci common_lock_depth(context) - returns common_lock_depth for the current event 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ciUtil.py Module 6038c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~ 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ciVarious utility functions for use with perf script: 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair 6088c2ecf20Sopenharmony_ci nsecs_secs(nsecs) - returns whole secs portion given nsecs 6098c2ecf20Sopenharmony_ci nsecs_nsecs(nsecs) - returns nsecs remainder given nsecs 6108c2ecf20Sopenharmony_ci nsecs_str(nsecs) - returns printable string in the form secs.nsecs 6118c2ecf20Sopenharmony_ci avg(total, n) - returns average given a sum and a total number of values 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ciSUPPORTED FIELDS 6148c2ecf20Sopenharmony_ci---------------- 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ciCurrently supported fields: 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ciev_name, comm, pid, tid, cpu, ip, time, period, phys_addr, addr, 6198c2ecf20Sopenharmony_cisymbol, dso, time_enabled, time_running, values, callchain, 6208c2ecf20Sopenharmony_cibrstack, brstacksym, datasrc, datasrc_decode, iregs, uregs, 6218c2ecf20Sopenharmony_ciweight, transaction, raw_buf, attr. 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ciSome fields have sub items: 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cibrstack: 6268c2ecf20Sopenharmony_ci from, to, from_dsoname, to_dsoname, mispred, 6278c2ecf20Sopenharmony_ci predicted, in_tx, abort, cycles. 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cibrstacksym: 6308c2ecf20Sopenharmony_ci items: from, to, pred, in_tx, abort (converted string) 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ciFor example, 6338c2ecf20Sopenharmony_ciWe can use this code to print brstack "from", "to", "cycles". 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ciif 'brstack' in dict: 6368c2ecf20Sopenharmony_ci for entry in dict['brstack']: 6378c2ecf20Sopenharmony_ci print "from %s, to %s, cycles %s" % (entry["from"], entry["to"], entry["cycles"]) 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ciSEE ALSO 6408c2ecf20Sopenharmony_ci-------- 6418c2ecf20Sopenharmony_cilinkperf:perf-script[1] 642