#!/bin/bash cliHandleDebugCommands() { local action="$initial_command2" case "$action" in ""|help) cliShowDebugHelp ;; load-trace) cliDebugLoadTrace ;; *) isNotice "Invalid debug action: $action" cliShowDebugHelp ;; esac } # Run `libreportal ` with LP_LOAD_TRACE=1, then summarise the resulting # trace file. We rebuild the args from initial_command3..7 (the CLI dispatcher # doesn't pass $@ to category handlers — same constraint as the peer commands). # A child shell invocation isolates the trace so it doesn't pollute the # currently-loaded process. cliDebugLoadTrace() { local args=() local a for a in "$initial_command3" "$initial_command4" "$initial_command5" "$initial_command6" "$initial_command7"; do [[ -n "$a" ]] && args+=("$a") done [[ ${#args[@]} -eq 0 ]] && args=(help) local trace_file trace_file=$(mktemp -t libreportal-load-trace.XXXXXX.log) isHeader "Load trace: libreportal ${args[*]}" # Time the whole child invocation so we can compare 'wall' vs 'time spent # in sourced files'. The diff = bash startup + dispatch + the command's # own work (which for `help` is ~nothing, so wall ≈ load + bash startup). local t0 t1 wall_ms t0=$EPOCHREALTIME LP_LOAD_TRACE=1 LP_LOAD_TRACE_FILE="$trace_file" \ libreportal "${args[@]}" >/dev/null 2>&1 t1=$EPOCHREALTIME wall_ms=$(awk -v a="$t0" -v b="$t1" 'BEGIN{printf "%.1f", (b-a)*1000}') if [[ ! -s "$trace_file" ]]; then isError "Trace file empty — did the child invocation actually source files?" rm -f "$trace_file" return 1 fi # Aggregate: total ms inside source, count, top-N hottest files. awk single # pass — no need for sort | head | wc dance. awk -v wall="$wall_ms" -v file="$trace_file" ' { ms=$1; sub(/^[^\t]*\t/,""); path=$0 total+=ms; n++ if (ms > 0.1) { top_ms[n]=ms; top_path[n]=path } } END { printf " Wall time (child invocation): %s ms\n", wall printf " Files sourced: %d\n", n printf " Cumulative source time: %.1f ms\n", total if (n>0) printf " Average per file: %.3f ms\n", total/n printf "\n Top 15 hottest files (>0.1 ms):\n" # Quick sort by ms descending (small N, n^2 is fine). for (i=1;i<=n;i++) for (j=i+1;j<=n;j++) if (top_ms[j]>top_ms[i]) { t=top_ms[i]; top_ms[i]=top_ms[j]; top_ms[j]=t t=top_path[i]; top_path[i]=top_path[j]; top_path[j]=t } shown=0 for (i=1;i<=n && shown<15;i++) if (top_ms[i]>0) { printf " %8.3f ms %s\n", top_ms[i], top_path[i] shown++ } printf "\n Full trace at: %s\n", file } ' "$trace_file" }