nigig-org/nimanyatta/analyse_instruments.sh
andodeki fd8b0632ca
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
Include nimanyatta as normal tree (not embedded git)
2026-09-26 09:29:36 +03:00

191 lines
No EOL
7.7 KiB
Bash
Executable file

#!/bin/bash
# analyse_instruments.sh
# Usage: ./analyse_instruments.sh instruments_output_20260513_212052
set -uo pipefail
OUTPUT_DIR="${1:?Usage: $0 <output_dir>}"
if [[ ! -d "$OUTPUT_DIR" ]]; then
echo "❌ Directory not found: $OUTPUT_DIR"
exit 1
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "INSTRUMENTS SESSION ANALYSIS"
echo "Directory: $OUTPUT_DIR"
echo "Analysed: $(date)"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# ── Session summary ───────────────────────────────────────────────────────
SUMMARY="${OUTPUT_DIR}/00_summary.txt"
if [[ -f "$SUMMARY" ]]; then
echo "── Session Summary ──────────────────────────────────────────────"
cat "$SUMMARY"
echo ""
fi
# ── Per-template results ──────────────────────────────────────────────────
echo "── Template Results ─────────────────────────────────────────────"
printf " %-30s %-6s %-8s %s\n" "Template" "Status" "Elapsed" "Trace"
printf " %-30s %-6s %-8s %s\n" \
"──────────────────────────────" "──────" "────────" "─────"
PASS_COUNT=0
SKIP_COUNT=0
FAIL_COUNT=0
MISSING_COUNT=0
for log in "${OUTPUT_DIR}"/*.txt; do
# Skip the summary file and load tester logs
[[ "$log" == *"00_summary"* ]] && continue
[[ "$log" == *"_load_tester"* ]] && continue
[[ -f "$log" ]] || continue
name=$(basename "$log" .txt | tr '_' ' ')
# Extract status and elapsed — handle both old and new log formats
status=$(grep "^Status:" "$log" 2>/dev/null | tail -1 | sed 's/^Status:[ ]*//')
elapsed=$(grep "^Elapsed:" "$log" 2>/dev/null | tail -1 | sed 's/^Elapsed:[ ]*//')
# Fallback if fields are empty
[[ -z "$status" ]] && status="unknown"
[[ -z "$elapsed" ]] && elapsed="?"
# Check if a trace file was copied for this template
SAFE=$(echo "$name" | tr ' ' '_')
if [[ -d "${OUTPUT_DIR}/${SAFE}.trace" ]]; then
trace_status="✅ yes"
else
trace_status="❌ no"
MISSING_COUNT=$((MISSING_COUNT + 1))
fi
icon="✅"
case "$status" in
PASS) PASS_COUNT=$((PASS_COUNT + 1)) ;;
SKIP) SKIP_COUNT=$((SKIP_COUNT + 1)); icon="⚠️ " ;;
FAIL) FAIL_COUNT=$((FAIL_COUNT + 1)); icon="❌" ;;
*) icon="❓" ;;
esac
printf " %-30s %s %-4s %-8s %s\n" \
"$name" "$icon" "$status" "$elapsed" "$trace_status"
done
echo ""
echo " Pass: $PASS_COUNT Skip: $SKIP_COUNT Fail: $FAIL_COUNT Missing traces: $MISSING_COUNT"
echo ""
# ── Trace files ───────────────────────────────────────────────────────────
echo "── Trace Files in Output Directory ─────────────────────────────"
TRACE_COUNT=0
while IFS= read -r -d '' trace; do
size=$(du -sh "$trace" 2>/dev/null | awk '{print $1}')
name=$(basename "$trace")
printf " %-40s %s\n" "$name" "$size"
TRACE_COUNT=$((TRACE_COUNT + 1))
done < <(find "$OUTPUT_DIR" -name "*.trace" -print0 2>/dev/null)
if [[ $TRACE_COUNT -eq 0 ]]; then
echo " No .trace files found in $OUTPUT_DIR"
echo ""
echo " Searching common locations for recent traces…"
FOUND_ELSEWHERE=false
for search_dir in \
"${HOME}/Library/Instruments" \
"${HOME}/Documents/Instruments" \
"target/instruments"; do
if [[ -d "$search_dir" ]]; then
COUNT=$(find "$search_dir" -name "*.trace" -maxdepth 3 2>/dev/null | wc -l | tr -d ' ')
if [[ "$COUNT" -gt 0 ]]; then
echo " Found $COUNT trace(s) in: $search_dir"
find "$search_dir" -name "*.trace" -maxdepth 3 2>/dev/null \
| sort -r | head -5 | sed 's/^/ /'
FOUND_ELSEWHERE=true
fi
fi
done
if [[ "$FOUND_ELSEWHERE" == "true" ]]; then
echo ""
echo " To copy them to the output directory:"
echo " cp -r ~/Library/Instruments/*.trace ${OUTPUT_DIR}/"
fi
fi
echo ""
# ── Load tester output during each template ───────────────────────────────
LOAD_LOGS=("${OUTPUT_DIR}"/*_load_tester.txt)
# Check if glob expanded (bash 3.2 compatible way)
if [[ -f "${LOAD_LOGS[0]}" ]]; then
echo "── Load Tester Output Per Template ─────────────────────────────"
for load_log in "${LOAD_LOGS[@]}"; do
[[ -f "$load_log" ]] || continue
template_name=$(basename "$load_log" _load_tester.txt | tr '_' ' ')
echo ""
echo " During: $template_name"
echo " $(printf '─%.0s' {1..50})"
if grep -q "CONCLUSION" "$load_log" 2>/dev/null; then
# Load tester completed — show the summary table
grep -A 30 "PROGRESSIVE LOAD REPORT" "$load_log" 2>/dev/null \
| head -30 | sed 's/^/ /'
elif grep -q "connected" "$load_log" 2>/dev/null; then
# Partial run — show last meaningful output
echo " (Partial run — load tester did not complete all profiles)"
grep "connected\|registered\|PASS\|FAIL\|Duration" "$load_log" \
2>/dev/null | tail -10 | sed 's/^/ /'
else
echo " (Load tester did not reach the server during this capture)"
tail -5 "$load_log" | sed 's/^/ /'
fi
done
echo ""
fi
# ── What to open ─────────────────────────────────────────────────────────
echo "── Next Steps ───────────────────────────────────────────────────"
echo ""
if [[ $TRACE_COUNT -gt 0 ]]; then
echo " Open all traces in Instruments.app:"
echo " open ${OUTPUT_DIR}/*.trace"
echo ""
echo " Priority order:"
for priority_name in \
"Time_Profiler" \
"Locks" \
"Thread_States" \
"Allocations" \
"Leaks" \
"Network"; do
trace="${OUTPUT_DIR}/${priority_name}.trace"
if [[ -d "$trace" ]]; then
echo " open \"${trace}\""
fi
done
else
echo " ⚠️ No traces in output directory."
echo " Run the profiling script again, or copy traces manually."
echo ""
echo " Quick re-run of the most important templates:"
echo " ./run_instruments.sh --template \"Time Profiler\" --time-limit 90"
echo " ./run_instruments.sh --template \"Locks\" --time-limit 90"
echo " ./run_instruments.sh --template \"Allocations\" --time-limit 90"
fi
echo ""
echo " Re-run a single template:"
echo " ./run_instruments.sh --template \"Time Profiler\" --time-limit 120"
echo ""
echo " Re-run everything:"
echo " pkill $BINARY 2>/dev/null || true"
echo " ./run_instruments.sh"
echo ""