|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# Memory Leak Test Script for all-smi API mode |
| 4 | +# |
| 5 | +# This script monitors memory usage while repeatedly querying the API endpoint. |
| 6 | +# It helps detect memory leaks by tracking RSS growth over time. |
| 7 | +# |
| 8 | +# Usage: |
| 9 | +# ./tests/memory-leak-test.sh [PORT] [DURATION_SECONDS] |
| 10 | +# |
| 11 | +# Example: |
| 12 | +# ./target/release/all-smi api --port 19090 & |
| 13 | +# ./tests/memory-leak-test.sh 19090 60 |
| 14 | + |
| 15 | +PORT=${1:-19090} |
| 16 | +DURATION=${2:-60} |
| 17 | +QUERY_INTERVAL=0.1 |
| 18 | +MONITOR_INTERVAL=1 |
| 19 | + |
| 20 | +PID=$(pgrep -f "all-smi api" | head -1) |
| 21 | + |
| 22 | +if [ -z "$PID" ]; then |
| 23 | + echo "Error: all-smi api process not found" |
| 24 | + echo "Please start all-smi in API mode first:" |
| 25 | + echo " ./target/release/all-smi api --port $PORT &" |
| 26 | + exit 1 |
| 27 | +fi |
| 28 | + |
| 29 | +echo "==========================================" |
| 30 | +echo "Memory Leak Test for all-smi API mode" |
| 31 | +echo "==========================================" |
| 32 | +echo "PID: $PID" |
| 33 | +echo "Port: $PORT" |
| 34 | +echo "Duration: ${DURATION}s" |
| 35 | +echo "==========================================" |
| 36 | + |
| 37 | +MEMORY_LOG=$(mktemp) |
| 38 | +QUERY_LOG=$(mktemp) |
| 39 | + |
| 40 | +INITIAL_RSS=$(ps -o rss= -p $PID | tr -d ' ') |
| 41 | +echo "Initial RSS: ${INITIAL_RSS} KB" |
| 42 | +echo "" |
| 43 | + |
| 44 | +# Memory monitoring |
| 45 | +( |
| 46 | + START_TIME=$(date +%s) |
| 47 | + while true; do |
| 48 | + CURRENT_TIME=$(date +%s) |
| 49 | + ELAPSED=$((CURRENT_TIME - START_TIME)) |
| 50 | + [ $ELAPSED -ge $DURATION ] && break |
| 51 | + RSS=$(ps -o rss= -p $PID 2>/dev/null | tr -d ' ') |
| 52 | + [ -n "$RSS" ] && echo "$ELAPSED $RSS" >> "$MEMORY_LOG" |
| 53 | + sleep $MONITOR_INTERVAL |
| 54 | + done |
| 55 | +) & |
| 56 | +MONITOR_PID=$! |
| 57 | + |
| 58 | +# Query loop |
| 59 | +( |
| 60 | + QUERY_COUNT=0 |
| 61 | + START_TIME=$(date +%s) |
| 62 | + while true; do |
| 63 | + CURRENT_TIME=$(date +%s) |
| 64 | + ELAPSED=$((CURRENT_TIME - START_TIME)) |
| 65 | + [ $ELAPSED -ge $DURATION ] && break |
| 66 | + curl -s "http://localhost:$PORT/metrics" > /dev/null 2>&1 |
| 67 | + QUERY_COUNT=$((QUERY_COUNT + 1)) |
| 68 | + [ $((QUERY_COUNT % 100)) -eq 0 ] && echo "Queries: $QUERY_COUNT, Elapsed: ${ELAPSED}s" >> "$QUERY_LOG" |
| 69 | + sleep $QUERY_INTERVAL |
| 70 | + done |
| 71 | + echo "Total queries: $QUERY_COUNT" >> "$QUERY_LOG" |
| 72 | +) & |
| 73 | +QUERY_PID=$! |
| 74 | + |
| 75 | +echo "Running test..." |
| 76 | +for i in $(seq 1 $DURATION); do |
| 77 | + sleep 1 |
| 78 | + RSS=$(ps -o rss= -p $PID 2>/dev/null | tr -d ' ') |
| 79 | + [ -n "$RSS" ] && printf "\r[%3d/%3ds] RSS: %d KB (D %+d KB)" $i $DURATION $RSS $((RSS - INITIAL_RSS)) |
| 80 | +done |
| 81 | +echo "" |
| 82 | +echo "" |
| 83 | + |
| 84 | +wait $MONITOR_PID 2>/dev/null |
| 85 | +wait $QUERY_PID 2>/dev/null |
| 86 | + |
| 87 | +FINAL_RSS=$(ps -o rss= -p $PID | tr -d ' ') |
| 88 | + |
| 89 | +echo "==========================================" |
| 90 | +echo "Test Results" |
| 91 | +echo "==========================================" |
| 92 | +echo "Initial RSS: ${INITIAL_RSS} KB" |
| 93 | +echo "Final RSS: ${FINAL_RSS} KB" |
| 94 | +echo "Difference: $((FINAL_RSS - INITIAL_RSS)) KB" |
| 95 | +echo "" |
| 96 | + |
| 97 | +if [ -f "$MEMORY_LOG" ]; then |
| 98 | + MIN_RSS=$(awk '{print $2}' "$MEMORY_LOG" | sort -n | head -1) |
| 99 | + MAX_RSS=$(awk '{print $2}' "$MEMORY_LOG" | sort -n | tail -1) |
| 100 | + AVG_RSS=$(awk '{sum+=$2; count++} END {printf "%.0f", sum/count}' "$MEMORY_LOG") |
| 101 | + echo "Statistics:" |
| 102 | + echo " Min RSS: ${MIN_RSS} KB" |
| 103 | + echo " Max RSS: ${MAX_RSS} KB" |
| 104 | + echo " Avg RSS: ${AVG_RSS} KB" |
| 105 | + echo " Range: $((MAX_RSS - MIN_RSS)) KB" |
| 106 | + echo "" |
| 107 | +fi |
| 108 | + |
| 109 | +cat "$QUERY_LOG" |
| 110 | +echo "" |
| 111 | + |
| 112 | +FIRST_AVG=$(head -5 "$MEMORY_LOG" | awk '{sum+=$2; count++} END {printf "%.0f", sum/count}') |
| 113 | +LAST_AVG=$(tail -5 "$MEMORY_LOG" | awk '{sum+=$2; count++} END {printf "%.0f", sum/count}') |
| 114 | +TREND=$((LAST_AVG - FIRST_AVG)) |
| 115 | + |
| 116 | +echo "==========================================" |
| 117 | +echo "Trend Analysis" |
| 118 | +echo "==========================================" |
| 119 | +echo "First 5 samples avg: ${FIRST_AVG} KB" |
| 120 | +echo "Last 5 samples avg: ${LAST_AVG} KB" |
| 121 | +echo "Trend: ${TREND} KB" |
| 122 | +echo "" |
| 123 | + |
| 124 | +if [ $TREND -gt 1000 ]; then |
| 125 | + echo "WARNING: Memory appears to be increasing significantly!" |
| 126 | + echo "This could indicate a memory leak." |
| 127 | + EXIT_CODE=1 |
| 128 | +elif [ $TREND -gt 100 ]; then |
| 129 | + echo "NOTICE: Memory shows some increase." |
| 130 | + echo "Consider running a longer test to confirm stability." |
| 131 | + EXIT_CODE=0 |
| 132 | +else |
| 133 | + echo "Memory appears stable." |
| 134 | + EXIT_CODE=0 |
| 135 | +fi |
| 136 | + |
| 137 | +rm -f "$MEMORY_LOG" "$QUERY_LOG" |
| 138 | +exit $EXIT_CODE |
0 commit comments