mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2026-08-24 04:36:39 +00:00
119 lines
2.9 KiB
Bash
119 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -u
|
|
|
|
DURATION="${1:-20}"
|
|
RATE="${2:-20}"
|
|
TIMESTAMP="$(date '+%Y%m%d-%H%M%S')"
|
|
OUTPUT_DIR="$HOME/Desktop/qortal-python-profile-$TIMESTAMP"
|
|
|
|
if ! command -v py-spy >/dev/null 2>&1; then
|
|
if command -v brew >/dev/null 2>&1; then
|
|
echo "Installing py-spy..."
|
|
brew install py-spy || exit 1
|
|
else
|
|
echo "Homebrew is unavailable. Install py-spy manually."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
PYSPY="$(command -v py-spy)"
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# Anchored patterns prevent the script, Codex, grep, and py-spy itself
|
|
# from being mistaken for Qortal processes.
|
|
BRIDGE_PIDS="$(
|
|
pgrep -f '^/Applications/.*/Python .*\/presence_bridge\.py --config ' || true
|
|
)"
|
|
|
|
RNSD_PIDS="$(
|
|
pgrep -f '^/Applications/.*/Python .*\/rnsd --config ' || true
|
|
)"
|
|
|
|
if [ -z "$BRIDGE_PIDS" ] && [ -z "$RNSD_PIDS" ]; then
|
|
echo "No Qortal presence_bridge or rnsd processes were found."
|
|
echo "Start Qortal Hub and run this script again."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Output directory: $OUTPUT_DIR"
|
|
echo "Bridge PIDs: ${BRIDGE_PIDS:-none}"
|
|
echo "rnsd PIDs: ${RNSD_PIDS:-none}"
|
|
echo
|
|
echo "Requesting administrator access..."
|
|
|
|
sudo -v || exit 1
|
|
|
|
{
|
|
echo "Captured: $(date)"
|
|
echo "Duration: ${DURATION}s"
|
|
echo "Rate: ${RATE} samples/second"
|
|
echo "py-spy: $PYSPY"
|
|
echo
|
|
uname -a
|
|
echo
|
|
echo "Qortal Python processes:"
|
|
for pid in $BRIDGE_PIDS $RNSD_PIDS; do
|
|
ps -p "$pid" -o pid=,ppid=,%cpu=,etime=,command=
|
|
done
|
|
} > "$OUTPUT_DIR/system-info.txt"
|
|
|
|
capture_process() {
|
|
local label="$1"
|
|
local pid="$2"
|
|
local profile="$OUTPUT_DIR/${label}-${pid}-profile.json"
|
|
local log="$OUTPUT_DIR/${label}-${pid}-profile.log"
|
|
local threads="$OUTPUT_DIR/${label}-${pid}-threads.txt"
|
|
local fallback="$OUTPUT_DIR/${label}-${pid}-macos-sample.txt"
|
|
|
|
echo "Preparing $label PID $pid..."
|
|
|
|
ps -p "$pid" -o pid=,ppid=,%cpu=,etime=,command= \
|
|
> "$OUTPUT_DIR/${label}-${pid}-process.txt"
|
|
|
|
sudo "$PYSPY" dump \
|
|
--nonblocking \
|
|
--pid "$pid" \
|
|
> "$threads" 2>&1 || true
|
|
|
|
(
|
|
sudo "$PYSPY" record \
|
|
--nonblocking \
|
|
--rate "$RATE" \
|
|
--duration "$DURATION" \
|
|
--pid "$pid" \
|
|
--format speedscope \
|
|
--output "$profile" \
|
|
> "$log" 2>&1
|
|
|
|
if [ ! -s "$profile" ]; then
|
|
echo "py-spy failed; collecting macOS sample fallback." >> "$log"
|
|
sample "$pid" "$DURATION" 10 -file "$fallback" \
|
|
>> "$log" 2>&1 || true
|
|
fi
|
|
) &
|
|
}
|
|
|
|
for pid in $BRIDGE_PIDS; do
|
|
capture_process "presence-bridge" "$pid"
|
|
done
|
|
|
|
for pid in $RNSD_PIDS; do
|
|
capture_process "rnsd" "$pid"
|
|
done
|
|
|
|
echo
|
|
echo "Recording simultaneously for ${DURATION} seconds..."
|
|
wait
|
|
|
|
echo
|
|
echo "Capture results:"
|
|
find "$OUTPUT_DIR" -type f -maxdepth 1 -exec ls -lh {} \;
|
|
|
|
ZIP_PATH="$OUTPUT_DIR.zip"
|
|
|
|
ditto -c -k --sequesterRsrc --keepParent \
|
|
"$OUTPUT_DIR" "$ZIP_PATH"
|
|
|
|
echo
|
|
echo "Finished: $ZIP_PATH" |