PID=${1:-$(pgrep -f "cyb.app/Contents/MacOS/app" | head -1)}
DURATION=${2:-60}
INTERVAL=10
OUTDIR="/tmp/cyb-profile-$(date +%Y%m%d_%H%M%S)"
if [ -z "$PID" ]; then
echo "ERROR: cyb.app not running. Pass PID as argument or launch the app first."
exit 1
fi
mkdir -p "$OUTDIR"
echo "Profiling PID $PID for ${DURATION}s, sampling every ${INTERVAL}s"
echo "Output: $OUTDIR"
echo "---"
echo "[$(date +%H:%M:%S)] Initial snapshot..."
heap --sortBySize "$PID" > "$OUTDIR/heap_start.txt" 2>&1
vmmap --summary "$PID" > "$OUTDIR/vmmap_start.txt" 2>&1
leaks --noContent "$PID" > "$OUTDIR/leaks_start.txt" 2>&1
echo "timestamp,rss_mb,virt_mb,cpu_pct" > "$OUTDIR/memory_timeline.csv"
ELAPSED=0
while [ $ELAPSED -lt $DURATION ]; do
STATS=$(ps -o rss=,vsz=,%cpu= -p "$PID" 2>/dev/null)
if [ -z "$STATS" ]; then
echo "[$(date +%H:%M:%S)] Process exited!"
break
fi
RSS=$(echo "$STATS" | awk '{print $1/1024}')
VSZ=$(echo "$STATS" | awk '{print $2/1024}')
CPU=$(echo "$STATS" | awk '{print $3}')
echo "$(date +%H:%M:%S),$RSS,$VSZ,$CPU" >> "$OUTDIR/memory_timeline.csv"
echo "[$(date +%H:%M:%S)] RSS: ${RSS}MB CPU: ${CPU}%"
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
done
echo "[$(date +%H:%M:%S)] Final snapshot..."
heap --sortBySize "$PID" > "$OUTDIR/heap_end.txt" 2>&1
vmmap --summary "$PID" > "$OUTDIR/vmmap_end.txt" 2>&1
leaks --noContent "$PID" > "$OUTDIR/leaks_end.txt" 2>&1
sample "$PID" 5 > "$OUTDIR/cpu_sample.txt" 2>&1
echo ""
echo "=== HEAP DIFF (top growers) ==="
START_BYTES=$(grep "total" "$OUTDIR/heap_start.txt" | grep -oE '[0-9]+ bytes' | head -1)
END_BYTES=$(grep "total" "$OUTDIR/heap_end.txt" | grep -oE '[0-9]+ bytes' | head -1)
echo "Start: $START_BYTES"
echo "End: $END_BYTES"
echo ""
echo "=== LEAK DIFF ==="
START_LEAKS=$(grep "leaks for" "$OUTDIR/leaks_start.txt" | head -1)
END_LEAKS=$(grep "leaks for" "$OUTDIR/leaks_end.txt" | head -1)
echo "Start: $START_LEAKS"
echo "End: $END_LEAKS"
echo ""
echo "=== MEMORY TIMELINE ==="
cat "$OUTDIR/memory_timeline.csv"
echo ""
echo "Full reports in: $OUTDIR"