@@ -18,8 +18,10 @@
# SESSIONS streams in a row against the same Sunshine and VM (default: 1)
# RESTART_VM_EVERY restart the guest with QMP system_reset after every N sessions (default: 0 = never)
# SAMPLE_SECONDS resource sampling interval (default: 5)
# MAX_RSS_GROWTH_MB allowed growth of Sunshine's RSS between the end of the first and the last session (default: 64)
# MAX_FD_GROWTH allowed growth of Sunshine's open descriptors between the same points (default: 8)
# MAX_RSS_GROWTH_MB allowed growth of Sunshine's RSS at the end of the last session over the highest RSS at the end
# of any session in the first half (default: 32). Allocators and encoder pools settle during the
# first streams, so growth against the first stream alone isn't a leak.
# MAX_FD_GROWTH allowed growth of Sunshine's open descriptors over the end of the first session (default: 8)
# ARTIFACTS output directory (default: a new directory under /tmp); gets summary-<n>.json, resources.csv,
# result.json and the logs
set -euo pipefail
@@ -40,7 +42,7 @@
sessions="${SESSIONS:-1}"
restart_every="${RESTART_VM_EVERY:-0}"
sample_seconds="${SAMPLE_SECONDS:-5}"
max_rss_growth_mb="${MAX_RSS_GROWTH_MB:-32}"
max_rss_growth_mb="${MAX_RSS_GROWTH_MB:-64}"
max_fd_growth="${MAX_FD_GROWTH:-8}"
artifacts="${ARTIFACTS:-$(mktemp -d "${TMPDIR:-/tmp}/sunshine-desktop.XXXXXX")}"
port="$((21000 + (RANDOM % 190) * 100))"
@@ -140,8 +142,8 @@
# 4. streams
timeout_s=$(( frames / stream_fps * 3 + 120 ))
first_end_rss=""
first_end_fds=""
first_half_max_rss=0
for ((session = 1; session <= sessions; session++)); do
echo "${session}" > "${work}/session"
set +e
@@ -160,9 +162,11 @@
rss=$(awk '/^VmRSS/ {print $2}' "/proc/${sunshine_pid}/status")
fds=$(ls "/proc/${sunshine_pid}/fd" | wc -l)
if (( session == 1 )); then
first_end_rss=${rss}
first_end_fds=${fds}
fi
if (( session <= (sessions + 1) / 2 && rss > first_half_max_rss )); then
first_half_max_rss=${rss}
fi
echo "desktop: stream ${session}/${sessions}: $(cat "${artifacts}/summary-${session}.json") rss=${rss}kB fds=${fds}" >&2
if (( restart_every > 0 && session % restart_every == 0 && session < sessions )); then
sleep 5
@@ -180,7 +184,7 @@
sampler_pid=""
cp -f "${work}/sunshine.log" "${work}/vm/qemu.log" "${artifacts}/" 2>/dev/null || true
rss_growth_kb=$(( rss - first_end_rss ))
rss_growth_kb=$(( rss - first_half_max_rss ))
fd_growth=$(( fds - first_end_fds ))
python3 - "${artifacts}" "${sessions}" "${rss_growth_kb}" "${fd_growth}" <<'EOF'
import glob, json, statistics, sys
@@ -194,7 +198,7 @@
"latency_p50_ms_median": statistics.median(p50) if p50 else None,
"latency_p95_ms_median": statistics.median(p95) if p95 else None,
"latency_p95_ms_max": max(p95) if p95 else None,
"rss_growth_kb_over_first_half_peak": rss_growth_kb,
"rss_growth_kb_after_first_session": rss_growth_kb,
"fd_growth_after_first_session": fd_growth,
}
json.dump(result, open(f"{artifacts}/result.json", "w"), indent=1)
@@ -203,7 +207,7 @@
if (( sessions > 1 )); then
if (( rss_growth_kb > max_rss_growth_mb * 1024 )); then
echo "desktop: FAIL: Sunshine RSS grew ${rss_growth_kb} kB after the first stream" >&2
echo "desktop: FAIL: Sunshine RSS at the end is ${rss_growth_kb} kB above its peak in the first half of the streams" >&2
exit 1
fi
if (( fd_growth > max_fd_growth )); then