|
| 1 | +#!/bin/bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +# Usage: ./run_perf_e2e.sh <pub_subs> <pure_subs> [top_n] [duration_sec] [output_dir] |
| 5 | +# Example: ./run_perf_e2e.sh 80 720 45 120 ./perf-results |
| 6 | + |
| 7 | +PUB_SUBS=${1:?Usage: $0 <pub_subs> <pure_subs> [top_n] [duration_sec] [output_dir]} |
| 8 | +PURE_SUBS=${2:?Usage: $0 <pub_subs> <pure_subs> [top_n] [duration_sec] [output_dir]} |
| 9 | +TOP_N=${3:-45} |
| 10 | +DURATION=${4:-120} |
| 11 | +OUTPUT_DIR=${5:-./perf-results} |
| 12 | + |
| 13 | +TOTAL_SUBS=$((PUB_SUBS + PURE_SUBS)) |
| 14 | +REMOTE="admin@snk-dev-1.m10x.org" |
| 15 | +SSH_KEY="$HOME/.ssh/keys/snk-dev-server.pem" |
| 16 | +SSH="ssh -i $SSH_KEY $REMOTE" |
| 17 | +SCP="scp -i $SSH_KEY" |
| 18 | +TIMESTAMP=$(date +%Y%m%d-%H%M%S) |
| 19 | +REMOTE_DIR="/tmp/moq-rs-perf-$TIMESTAMP" |
| 20 | +LOCAL_DIR="$OUTPUT_DIR/$TIMESTAMP" |
| 21 | + |
| 22 | +mkdir -p "$LOCAL_DIR" |
| 23 | + |
| 24 | +echo "=== MOQ-RS E2E Performance Test ===" |
| 25 | +echo " Publishers (pub-sub): $PUB_SUBS" |
| 26 | +echo " Pure subscribers: $PURE_SUBS" |
| 27 | +echo " Total subscribers: $TOTAL_SUBS" |
| 28 | +echo " Top-N filter: $TOP_N" |
| 29 | +echo " Duration: ${DURATION}s" |
| 30 | +echo " Remote: $REMOTE" |
| 31 | +echo " Remote dir: $REMOTE_DIR" |
| 32 | +echo " Local output: $LOCAL_DIR" |
| 33 | +echo "" |
| 34 | + |
| 35 | +# Step 1: Collect system info |
| 36 | +echo "[1/7] Collecting system configuration..." |
| 37 | +$SSH "bash -s" > "$LOCAL_DIR/sysinfo.txt" <<'SYSINFO' |
| 38 | +echo "=== System Configuration ===" |
| 39 | +echo "Hostname: $(hostname)" |
| 40 | +echo "Date: $(date -u)" |
| 41 | +echo "Kernel: $(uname -r)" |
| 42 | +echo "Arch: $(uname -m)" |
| 43 | +echo "CPU:" |
| 44 | +lscpu | grep -E "^(Model name|CPU\(s\)|Thread|Core|Socket|CPU max)" |
| 45 | +echo "" |
| 46 | +echo "Memory:" |
| 47 | +free -h | head -2 |
| 48 | +echo "" |
| 49 | +echo "OS:" |
| 50 | +cat /etc/os-release 2>/dev/null | grep -E "^(NAME|VERSION)" || true |
| 51 | +echo "" |
| 52 | +echo "Rust:" |
| 53 | +source ~/.cargo/env 2>/dev/null |
| 54 | +rustc --version 2>/dev/null || echo "unknown" |
| 55 | +echo "" |
| 56 | +echo "Git commit:" |
| 57 | +cd ~/moq-rs-top-n && git log --oneline -1 |
| 58 | +echo "Git branch:" |
| 59 | +cd ~/moq-rs-top-n && git branch --show-current |
| 60 | +SYSINFO |
| 61 | + |
| 62 | +echo " Done." |
| 63 | + |
| 64 | +# Step 2: Build on remote |
| 65 | +echo "[2/7] Building on remote..." |
| 66 | +$SSH "cd ~/moq-rs-top-n && source ~/.cargo/env && cargo build --release --bin moq-relay-ietf --bin moq-topn-test 2>&1 | tail -3" |
| 67 | +echo " Done." |
| 68 | + |
| 69 | +# Step 3: Run perf test |
| 70 | +echo "[3/7] Running perf test (${DURATION}s + overhead)..." |
| 71 | +$SSH "bash -s" <<PERF_SCRIPT |
| 72 | +set -e |
| 73 | +cd ~/moq-rs-top-n |
| 74 | +source ~/.cargo/env |
| 75 | +mkdir -p $REMOTE_DIR |
| 76 | +
|
| 77 | +pkill -f moq-relay-ietf 2>/dev/null || true |
| 78 | +sleep 1 |
| 79 | +
|
| 80 | +# Start relay |
| 81 | +./target/release/moq-relay-ietf --bind "[::]:4443" --tls-cert cert.pem --tls-key key.pem > $REMOTE_DIR/relay.log 2>&1 & |
| 82 | +RELAY_PID=\$! |
| 83 | +sleep 2 |
| 84 | +
|
| 85 | +# Capture memory baseline |
| 86 | +ps -o rss= -p \$RELAY_PID > $REMOTE_DIR/mem_before.txt |
| 87 | +
|
| 88 | +# Start perf recording |
| 89 | +perf record -F 999 -p \$RELAY_PID -g -o $REMOTE_DIR/perf.data -- sleep $((DURATION + 15)) & |
| 90 | +PERF_PID=\$! |
| 91 | +
|
| 92 | +# Run e2e test |
| 93 | +./target/release/moq-topn-test -m e2e \\ |
| 94 | + --relay https://localhost:4443 \\ |
| 95 | + --tls-disable-verify \\ |
| 96 | + -x $PUB_SUBS \\ |
| 97 | + -y $TOTAL_SUBS \\ |
| 98 | + -n $TOP_N \\ |
| 99 | + -d $DURATION \\ |
| 100 | + --group-interval-ms 33 \\ |
| 101 | + --connection-batch-size 50 \\ |
| 102 | + > $REMOTE_DIR/test_output.txt 2>&1 || true |
| 103 | +
|
| 104 | +# Capture memory after test |
| 105 | +ps -o rss= -p \$RELAY_PID > $REMOTE_DIR/mem_after.txt 2>/dev/null || echo "0" > $REMOTE_DIR/mem_after.txt |
| 106 | +
|
| 107 | +wait \$PERF_PID 2>/dev/null || true |
| 108 | +
|
| 109 | +# Generate flamegraph |
| 110 | +perf script -i $REMOTE_DIR/perf.data | ~/FlameGraph/stackcollapse-perf.pl > $REMOTE_DIR/collapsed.txt |
| 111 | +~/FlameGraph/flamegraph.pl $REMOTE_DIR/collapsed.txt > $REMOTE_DIR/flamegraph.svg |
| 112 | +
|
| 113 | +# Run analysis |
| 114 | +python3 ~/moq-rs-top-n/tools/analyze_flamegraph.py $REMOTE_DIR/collapsed.txt $REMOTE_DIR/analysis.txt |
| 115 | +
|
| 116 | +kill \$RELAY_PID 2>/dev/null || true |
| 117 | +echo "DONE" > $REMOTE_DIR/status.txt |
| 118 | +PERF_SCRIPT |
| 119 | + |
| 120 | +echo " Done." |
| 121 | + |
| 122 | +# Step 4: Wait for completion and verify |
| 123 | +echo "[4/7] Verifying completion..." |
| 124 | +STATUS=$($SSH "cat $REMOTE_DIR/status.txt 2>/dev/null || echo FAILED") |
| 125 | +if [ "$STATUS" != "DONE" ]; then |
| 126 | + echo " ERROR: Test did not complete successfully" |
| 127 | + exit 1 |
| 128 | +fi |
| 129 | +echo " Done." |
| 130 | + |
| 131 | +# Step 5: Collect results |
| 132 | +echo "[5/7] Collecting results from remote..." |
| 133 | +$SCP "$REMOTE:$REMOTE_DIR/flamegraph.svg" "$LOCAL_DIR/flamegraph.svg" |
| 134 | +$SCP "$REMOTE:$REMOTE_DIR/collapsed.txt" "$LOCAL_DIR/collapsed.txt" |
| 135 | +$SCP "$REMOTE:$REMOTE_DIR/analysis.txt" "$LOCAL_DIR/analysis.txt" |
| 136 | +$SCP "$REMOTE:$REMOTE_DIR/test_output.txt" "$LOCAL_DIR/test_output.txt" |
| 137 | +$SCP "$REMOTE:$REMOTE_DIR/relay.log" "$LOCAL_DIR/relay.log" |
| 138 | +$SCP "$REMOTE:$REMOTE_DIR/mem_before.txt" "$LOCAL_DIR/mem_before.txt" |
| 139 | +$SCP "$REMOTE:$REMOTE_DIR/mem_after.txt" "$LOCAL_DIR/mem_after.txt" |
| 140 | +echo " Done." |
| 141 | + |
| 142 | +# Step 6: Extract test metrics from output |
| 143 | +echo "[6/7] Extracting metrics..." |
| 144 | +TEST_OUTPUT="$LOCAL_DIR/test_output.txt" |
| 145 | + |
| 146 | +# Extract key metrics from test output |
| 147 | +OBJECTS_SENT=$(grep -o "objects_sent\":[0-9]*" "$TEST_OUTPUT" | tail -1 | cut -d: -f2 || echo "N/A") |
| 148 | +OBJECTS_RECV=$(grep -o "objects_received\":[0-9]*" "$TEST_OUTPUT" | tail -1 | cut -d: -f2 || echo "N/A") |
| 149 | +FILTER_PASS=$(grep -c "TOPN_EVENT.*filter_pass" "$TEST_OUTPUT" 2>/dev/null || echo "0") |
| 150 | +FILTER_DROP=$(grep -c "TOPN_EVENT.*filter_drop" "$TEST_OUTPUT" 2>/dev/null || echo "0") |
| 151 | + |
| 152 | +# Memory |
| 153 | +MEM_BEFORE=$(cat "$LOCAL_DIR/mem_before.txt" | tr -d ' ') |
| 154 | +MEM_AFTER=$(cat "$LOCAL_DIR/mem_after.txt" | tr -d ' ') |
| 155 | +MEM_BEFORE_MB=$(echo "scale=1; $MEM_BEFORE / 1024" | bc 2>/dev/null || echo "N/A") |
| 156 | +MEM_AFTER_MB=$(echo "scale=1; $MEM_AFTER / 1024" | bc 2>/dev/null || echo "N/A") |
| 157 | + |
| 158 | +# Extract from analysis |
| 159 | +TOPN_SELF=$(grep "Total Top-N self time" "$LOCAL_DIR/analysis.txt" | grep -o "[0-9.]*%" | head -1 || echo "N/A") |
| 160 | +TOPN_INCLUSIVE=$(grep "Top-N compute (inclusive)" "$LOCAL_DIR/analysis.txt" | grep -o "[0-9.]*%" | head -1 || echo "N/A") |
| 161 | +QUIC_SELF=$(grep "QUIC transport (self)" "$LOCAL_DIR/analysis.txt" | grep -o "[0-9.]*%" | head -1 || echo "N/A") |
| 162 | +QUIC_INCLUSIVE=$(grep "QUIC Transport" "$LOCAL_DIR/analysis.txt" | head -1 | grep -o "[0-9.]*%" | head -1 || echo "N/A") |
| 163 | +MOQ_INCLUSIVE=$(grep "MOQ protocol (inclusive)" "$LOCAL_DIR/analysis.txt" | grep -o "[0-9.]*%" | head -1 || echo "N/A") |
| 164 | +ALLOC_SELF=$(grep "Memory Allocation" "$LOCAL_DIR/analysis.txt" | tail -1 | grep -o "[0-9.]*%" | head -1 || echo "N/A") |
| 165 | + |
| 166 | +echo " Done." |
| 167 | + |
| 168 | +# Step 7: Generate report |
| 169 | +echo "[7/7] Generating report..." |
| 170 | +REPORT="$LOCAL_DIR/report.md" |
| 171 | +SYSINFO=$(cat "$LOCAL_DIR/sysinfo.txt") |
| 172 | +ANALYSIS=$(cat "$LOCAL_DIR/analysis.txt") |
| 173 | + |
| 174 | +cat > "$REPORT" <<EOF |
| 175 | +# MOQ-RS Relay Performance Report |
| 176 | +
|
| 177 | +**Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC') |
| 178 | +**Commit:** $(grep "Git commit:" "$LOCAL_DIR/sysinfo.txt" | cut -d: -f2- | xargs) |
| 179 | +**Branch:** $(grep "Git branch:" "$LOCAL_DIR/sysinfo.txt" | cut -d: -f2- | xargs) |
| 180 | +
|
| 181 | +## Test Parameters |
| 182 | +
|
| 183 | +| Parameter | Value | |
| 184 | +|-----------|-------| |
| 185 | +| Publishers (pub-sub) | $PUB_SUBS | |
| 186 | +| Pure subscribers | $PURE_SUBS | |
| 187 | +| Total subscribers | $TOTAL_SUBS | |
| 188 | +| Top-N filter | $TOP_N | |
| 189 | +| Duration | ${DURATION}s | |
| 190 | +| Group interval | 33ms (~30 fps) | |
| 191 | +| Connection batch size | 50 | |
| 192 | +
|
| 193 | +## System Configuration |
| 194 | +
|
| 195 | +\`\`\` |
| 196 | +$SYSINFO |
| 197 | +\`\`\` |
| 198 | +
|
| 199 | +## Results Summary |
| 200 | +
|
| 201 | +### CPU Profile |
| 202 | +
|
| 203 | +| Component | Self Time | Inclusive Time | |
| 204 | +|-----------|-----------|----------------| |
| 205 | +| **Top-N** | $TOPN_SELF | $TOPN_INCLUSIVE | |
| 206 | +| QUIC Transport | $QUIC_SELF | $QUIC_INCLUSIVE | |
| 207 | +| MOQ Protocol | — | $MOQ_INCLUSIVE | |
| 208 | +| Memory Allocation | $ALLOC_SELF | — | |
| 209 | +
|
| 210 | +### Memory Usage |
| 211 | +
|
| 212 | +| Metric | Value | |
| 213 | +|--------|-------| |
| 214 | +| RSS before test | ${MEM_BEFORE_MB} MB | |
| 215 | +| RSS after test | ${MEM_AFTER_MB} MB | |
| 216 | +| Growth | $(echo "scale=1; ($MEM_AFTER - $MEM_BEFORE) / 1024" | bc 2>/dev/null || echo "N/A") MB | |
| 217 | +
|
| 218 | +### Top-N vs QUIC Relative Cost |
| 219 | +
|
| 220 | +- Self vs self: Top-N $TOPN_SELF vs QUIC $QUIC_SELF |
| 221 | +- Inclusive vs inclusive: Top-N $TOPN_INCLUSIVE vs QUIC $QUIC_INCLUSIVE |
| 222 | +
|
| 223 | +## Detailed Flamegraph Analysis |
| 224 | +
|
| 225 | +\`\`\` |
| 226 | +$ANALYSIS |
| 227 | +\`\`\` |
| 228 | +
|
| 229 | +## Artifacts |
| 230 | +
|
| 231 | +- \`flamegraph.svg\` — Interactive flamegraph |
| 232 | +- \`collapsed.txt\` — Collapsed stacks for custom analysis |
| 233 | +- \`test_output.txt\` — Full test driver output |
| 234 | +- \`relay.log\` — Relay server logs |
| 235 | +- \`analysis.txt\` — Raw flamegraph analysis |
| 236 | +
|
| 237 | +EOF |
| 238 | + |
| 239 | +echo " Done." |
| 240 | +echo "" |
| 241 | +echo "=== Report generated: $REPORT ===" |
| 242 | +echo "=== Flamegraph: $LOCAL_DIR/flamegraph.svg ===" |
0 commit comments