run-benchmark.sh raw
1 #!/bin/bash
2
3 # Wrapper script to run the benchmark suite and automatically shut down when complete
4 #
5 # Usage:
6 # ./run-benchmark.sh # Use disk-based storage (default)
7 # ./run-benchmark.sh --ramdisk # Use /dev/shm ramdisk for maximum performance
8 # ./run-benchmark.sh --graph # Also run graph traversal benchmarks
9
10 set -e
11
12 # Parse command line arguments
13 USE_RAMDISK=false
14 USE_GRAPH_TRAVERSAL=false
15 for arg in "$@"; do
16 case $arg in
17 --ramdisk)
18 USE_RAMDISK=true
19 shift
20 ;;
21 --graph)
22 USE_GRAPH_TRAVERSAL=true
23 shift
24 ;;
25 --help|-h)
26 echo "Usage: $0 [OPTIONS]"
27 echo ""
28 echo "Options:"
29 echo " --ramdisk Use /dev/shm ramdisk storage instead of disk"
30 echo " This eliminates disk I/O bottlenecks for accurate"
31 echo " relay performance measurement."
32 echo " --graph Run graph traversal benchmarks (100k pubkeys,"
33 echo " 1-1000 follows each, 3-degree traversal)"
34 echo " --help, -h Show this help message"
35 echo ""
36 echo "Requirements for --ramdisk:"
37 echo " - /dev/shm must be available (tmpfs mount)"
38 echo " - At least 8GB available in /dev/shm recommended"
39 echo " - Increase size with: sudo mount -o remount,size=16G /dev/shm"
40 exit 0
41 ;;
42 *)
43 echo "Unknown option: $arg"
44 echo "Use --help for usage information"
45 exit 1
46 ;;
47 esac
48 done
49
50 # Export graph traversal setting for docker-compose
51 export BENCHMARK_GRAPH_TRAVERSAL="${USE_GRAPH_TRAVERSAL}"
52
53 # Determine docker-compose command
54 if docker compose version &> /dev/null 2>&1; then
55 DOCKER_COMPOSE="docker compose"
56 else
57 DOCKER_COMPOSE="docker-compose"
58 fi
59
60 # Set data directory and compose files based on mode
61 if [ "$USE_RAMDISK" = true ]; then
62 DATA_BASE="/dev/shm/benchmark"
63 COMPOSE_FILES="-f docker-compose.yml -f docker-compose.ramdisk.yml"
64
65 echo "======================================================"
66 echo " RAMDISK BENCHMARK MODE"
67 echo "======================================================"
68
69 # Check /dev/shm availability
70 if [ ! -d "/dev/shm" ]; then
71 echo "ERROR: /dev/shm is not available on this system."
72 echo "This benchmark requires a tmpfs-mounted /dev/shm for RAM-based storage."
73 exit 1
74 fi
75
76 # Check available space in /dev/shm (need at least 8GB for benchmarks)
77 SHM_AVAILABLE_KB=$(df /dev/shm | tail -1 | awk '{print $4}')
78 SHM_AVAILABLE_GB=$((SHM_AVAILABLE_KB / 1024 / 1024))
79 echo " Storage location: ${DATA_BASE}"
80 echo " Available RAM: ${SHM_AVAILABLE_GB}GB"
81 echo " This eliminates disk I/O bottlenecks for accurate"
82 echo " relay performance measurement."
83 echo "======================================================"
84 echo ""
85
86 if [ "$SHM_AVAILABLE_KB" -lt 8388608 ]; then
87 echo "WARNING: Less than 8GB available in /dev/shm (${SHM_AVAILABLE_GB}GB available)"
88 echo "Benchmarks may fail if databases grow too large."
89 echo "Consider increasing tmpfs size: sudo mount -o remount,size=16G /dev/shm"
90 echo ""
91 read -p "Continue anyway? [y/N] " -n 1 -r
92 echo
93 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
94 exit 1
95 fi
96 fi
97 else
98 DATA_BASE="./data"
99 COMPOSE_FILES="-f docker-compose.yml"
100
101 echo "======================================================"
102 echo " DISK-BASED BENCHMARK MODE (default)"
103 echo "======================================================"
104 echo " Storage location: ${DATA_BASE}"
105 echo " Tip: Use --ramdisk for faster benchmarks without"
106 echo " disk I/O bottlenecks."
107 echo "======================================================"
108 echo ""
109 fi
110
111 # Show graph traversal status
112 if [ "$USE_GRAPH_TRAVERSAL" = true ]; then
113 echo "======================================================"
114 echo " GRAPH TRAVERSAL BENCHMARK ENABLED"
115 echo "======================================================"
116 echo " Will test 100k pubkeys with 1-1000 follows each"
117 echo " performing 3-degree graph traversal queries"
118 echo "======================================================"
119 echo ""
120 fi
121
122 # Clean old data directories (may be owned by root from Docker)
123 if [ -d "${DATA_BASE}" ]; then
124 echo "Cleaning old data directories at ${DATA_BASE}..."
125 if ! rm -rf "${DATA_BASE}" 2>/dev/null; then
126 # If normal rm fails (permission denied), try with sudo for ramdisk
127 if [ "$USE_RAMDISK" = true ]; then
128 echo "Need elevated permissions to clean ramdisk..."
129 if ! sudo rm -rf "${DATA_BASE}" 2>/dev/null; then
130 echo ""
131 echo "ERROR: Cannot remove data directories."
132 echo "Please run: sudo rm -rf ${DATA_BASE}"
133 echo "Then run this script again."
134 exit 1
135 fi
136 else
137 # Provide clear instructions for disk-based mode
138 echo ""
139 echo "ERROR: Cannot remove data directories due to permission issues."
140 echo "This happens because Docker creates files as root."
141 echo ""
142 echo "Please run one of the following to clean up:"
143 echo " sudo rm -rf ${DATA_BASE}/"
144 echo " sudo chown -R \$(id -u):\$(id -g) ${DATA_BASE}/ && rm -rf ${DATA_BASE}/"
145 echo ""
146 echo "Then run this script again."
147 exit 1
148 fi
149 fi
150 fi
151
152 # Stop any running containers from previous runs
153 echo "Stopping any running containers..."
154 $DOCKER_COMPOSE $COMPOSE_FILES down 2>/dev/null || true
155
156 # Create fresh data directories with correct permissions
157 echo "Preparing data directories at ${DATA_BASE}..."
158
159 if [ "$USE_RAMDISK" = true ]; then
160 # Create ramdisk directories
161 mkdir -p "${DATA_BASE}"/{next-orly-badger,next-orly-neo4j,neo4j,neo4j-logs,khatru-sqlite,khatru-badger,relayer-basic,strfry,nostr-rs-relay,rely-sqlite,postgres}
162 chmod 777 "${DATA_BASE}"/{next-orly-badger,next-orly-neo4j,neo4j,neo4j-logs,khatru-sqlite,khatru-badger,relayer-basic,strfry,nostr-rs-relay,rely-sqlite,postgres}
163 else
164 # Create disk directories (relative path)
165 mkdir -p data/{next-orly-badger,next-orly-neo4j,neo4j,neo4j-logs,khatru-sqlite,khatru-badger,relayer-basic,strfry,nostr-rs-relay,rely-sqlite,postgres}
166 chmod 777 data/{next-orly-badger,next-orly-neo4j,neo4j,neo4j-logs,khatru-sqlite,khatru-badger,relayer-basic,strfry,nostr-rs-relay,rely-sqlite,postgres}
167 fi
168
169 echo "Building fresh Docker images..."
170 # Force rebuild to pick up latest code changes
171 $DOCKER_COMPOSE $COMPOSE_FILES build --no-cache benchmark-runner next-orly-badger next-orly-neo4j rely-sqlite
172
173 echo ""
174 echo "Starting benchmark suite..."
175 echo "This will automatically shut down all containers when the benchmark completes."
176 echo ""
177
178 # Run docker compose with flags to exit when benchmark-runner completes
179 $DOCKER_COMPOSE $COMPOSE_FILES up --exit-code-from benchmark-runner --abort-on-container-exit
180
181 # Cleanup function
182 cleanup() {
183 echo ""
184 echo "Cleaning up..."
185 $DOCKER_COMPOSE $COMPOSE_FILES down 2>/dev/null || true
186
187 if [ "$USE_RAMDISK" = true ]; then
188 echo "Cleaning ramdisk data at ${DATA_BASE}..."
189 rm -rf "${DATA_BASE}" 2>/dev/null || sudo rm -rf "${DATA_BASE}" 2>/dev/null || true
190 fi
191 }
192
193 # Register cleanup on script exit
194 trap cleanup EXIT
195
196 echo ""
197 echo "Benchmark suite has completed and all containers have been stopped."
198 echo "Check the ./reports/ directory for results."
199