aboutsummaryrefslogtreecommitdiff
path: root/scripts/lib/trace-extract.awk
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/trace-extract.awk')
-rw-r--r--scripts/lib/trace-extract.awk71
1 files changed, 71 insertions, 0 deletions
diff --git a/scripts/lib/trace-extract.awk b/scripts/lib/trace-extract.awk
new file mode 100644
index 0000000..7b8682a
--- /dev/null
+++ b/scripts/lib/trace-extract.awk
@@ -0,0 +1,71 @@
+# scripts/lib/trace-extract.awk
+# Extract instrumented source locations from xtrace logs produced via
+# scripts/lib/trace-init.sh.
+#
+# Marker lines look like (bash repeats the leading '@' once per nesting level):
+# @@TBL@@ /path/to/trbldoc.sh:1234 1712345678.123456
+#
+# Variables:
+# MODE=cov (default) -> prints "<base>\t<line>" per marker line
+# MODE=time -> prints "<total_ms>\t<hits>\t<base>\t<line>" at END,
+# computing per-line durations from consecutive markers
+# WITHIN each trace file (one file == one process, so
+# parallel xargs workers are not cross-attributed).
+
+function basename(p) {
+ sub(/.*\//, "", p) # strip up to last forward slash
+ sub(/.*\\/, "", p) # strip up to last backslash (defensive)
+ return p
+}
+
+# Parse a marker line into globals g_base and g_line (and g_epoch for time).
+# Returns 1 on success, 0 if the line is not a usable marker.
+function parse(line, s, n, f, loc, rest) {
+ if (line !~ /@+TBL@@ /) return 0
+ s = line
+ sub(/^.*TBL@@ /, "", s) # drop marker and everything before it
+ n = split(s, f, " ")
+ if (n < 1) return 0
+ loc = f[1] # <source>:<lineno>
+ if (!match(loc, /:[0-9]+$/)) return 0
+ g_line = substr(loc, RSTART + 1)
+ g_base = basename(substr(loc, 1, RSTART - 1))
+ if (MODE == "time") {
+ g_epoch = (n >= 2 ? f[2] : "")
+ }
+ return 1
+}
+
+BEGIN { if (MODE == "") MODE = "cov" }
+
+# Reset per-process state at the start of each trace file.
+FNR == 1 { have_prev = 0 }
+
+{
+ if (!parse($0)) next
+ if (MODE == "cov") {
+ print g_base "\t" g_line
+ next
+ }
+ # MODE == time: attribute elapsed time to the PREVIOUS marker.
+ if (have_prev && g_epoch != "" && prev_epoch != "") {
+ d = g_epoch - prev_epoch
+ if (d < 0) d = 0
+ key = prev_base SUBSEP prev_line
+ ms[key] += d * 1000.0
+ hits[key] += 1
+ base_of[key] = prev_base
+ line_of[key] = prev_line
+ }
+ prev_base = g_base
+ prev_line = g_line
+ prev_epoch = g_epoch
+ have_prev = 1
+}
+
+END {
+ if (MODE != "time") exit
+ for (k in ms) {
+ printf "%.3f\t%d\t%s\t%s\n", ms[k], hits[k], base_of[k], line_of[k]
+ }
+}