#!/usr/bin/awk -f # # This script reads a list of kernel functions, one per line, and outputs a # systemtap script set to collect timing information for those functions, so # that microsecond counts are kept in statistics variables, one per function, # and the call counts, minimum time spend, average time spent and maximum # time spent is printed as the systemtap output when it is stopped. # # It should be useful to measure timing differences between kernel releases # or between different settings for kernel tunables, thus helping either # focus development/tuning attempts or decide what is the best tunable set. BEGIN { print "global entry, timings"; print; print "function collect_entry() { entry[probefunc(),pid()] = gettimeofday_us() }"; print "function collect_exit() { timings[probefunc()] <<< (gettimeofday_us() - entry[probefunc(),pid()]) }"; print; }; { if (NF == 0 || substr($0, 0, 1) == "#") next; printf("# Filename: %s Line: %d\n", FILENAME, FNR); if (NF == 1) { if ($1 in probes) { printf("# Not generating duplicate probe for %s\n\n", $1); } else { printf("probe kernel.function(\"%s\") { collect_entry(); }\n", $1); printf("probe kernel.function(\"%s\").return { collect_exit(); }\n\n", $1); probes[$1] = 1; } } else if (NF == 2) { if (($1,$2) in probes) { printf("# Not generating duplicate probe for %s:%s\n\n", $1, $2); } else { printf("probe module(\"%s\").function(\"%s\") { collect_entry(); }\n", $1, $2); printf("probe module(\"%s\").function(\"%s\").return { collect_exit(); }\n\n", $1, $2); probes[$1,$2] = 1; } } else { print "# Don't know what do do with this line:"; print "#", $0, "\n"; } }; END { print "probe end {"; print " printf(\"function count min_us avg_us max_us\\n\")"; print " foreach (i+ in timings) {"; print " printf(\"%-25s %7d %8d %8d %8d\\n\", i, @count(timings[i]),"; print " @min(timings[i]), @avg(timings[i]), @max(timings[i]))"; print " }"; print "}"; };