run-performance-tests.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #!/bin/bash
  2. set -euo pipefail
  3. # Colors for output
  4. RED='\033[0;31m'
  5. GREEN='\033[0;32m'
  6. BLUE='\033[0;34m'
  7. YELLOW='\033[1;33m'
  8. NC='\033[0m' # No Color
  9. # Configuration
  10. MOUNT_POINT=${MOUNT_POINT:-"/mnt/seaweedfs"}
  11. RDMA_SIDECAR_ADDR=${RDMA_SIDECAR_ADDR:-"rdma-sidecar:8081"}
  12. PERFORMANCE_RESULTS_DIR=${PERFORMANCE_RESULTS_DIR:-"/performance-results"}
  13. # Create results directory
  14. mkdir -p "$PERFORMANCE_RESULTS_DIR"
  15. # Log file
  16. LOG_FILE="$PERFORMANCE_RESULTS_DIR/performance-test.log"
  17. exec > >(tee -a "$LOG_FILE")
  18. exec 2>&1
  19. echo -e "${BLUE}🏁 SEAWEEDFS RDMA MOUNT PERFORMANCE TESTS${NC}"
  20. echo "==========================================="
  21. echo "Mount Point: $MOUNT_POINT"
  22. echo "RDMA Sidecar: $RDMA_SIDECAR_ADDR"
  23. echo "Results Directory: $PERFORMANCE_RESULTS_DIR"
  24. echo "Log File: $LOG_FILE"
  25. echo ""
  26. # Function to wait for mount to be ready
  27. wait_for_mount() {
  28. local max_attempts=30
  29. local attempt=1
  30. echo -e "${BLUE}⏳ Waiting for mount to be ready...${NC}"
  31. while [[ $attempt -le $max_attempts ]]; do
  32. if mountpoint -q "$MOUNT_POINT" 2>/dev/null && ls "$MOUNT_POINT" >/dev/null 2>&1; then
  33. echo -e "${GREEN}✅ Mount is ready${NC}"
  34. return 0
  35. fi
  36. echo " Attempt $attempt/$max_attempts..."
  37. sleep 2
  38. ((attempt++))
  39. done
  40. echo -e "${RED}❌ Mount failed to be ready${NC}"
  41. return 1
  42. }
  43. # Function to get RDMA statistics
  44. get_rdma_stats() {
  45. curl -s "http://$RDMA_SIDECAR_ADDR/stats" 2>/dev/null || echo "{}"
  46. }
  47. # Function to run dd performance test
  48. run_dd_test() {
  49. local test_name=$1
  50. local file_size_mb=$2
  51. local block_size=$3
  52. local operation=$4 # "write" or "read"
  53. local test_file="$MOUNT_POINT/perf_test_${test_name}.dat"
  54. local result_file="$PERFORMANCE_RESULTS_DIR/dd_${test_name}.json"
  55. echo -e "${BLUE}🔬 Running DD test: $test_name${NC}"
  56. echo " Size: ${file_size_mb}MB, Block Size: $block_size, Operation: $operation"
  57. local start_time end_time duration_ms throughput_mbps
  58. if [[ "$operation" == "write" ]]; then
  59. start_time=$(date +%s%N)
  60. dd if=/dev/zero of="$test_file" bs="$block_size" count=$((file_size_mb * 1024 * 1024 / $(numfmt --from=iec "$block_size"))) 2>/dev/null
  61. end_time=$(date +%s%N)
  62. else
  63. # Create file first if it doesn't exist
  64. if [[ ! -f "$test_file" ]]; then
  65. dd if=/dev/zero of="$test_file" bs=1M count="$file_size_mb" 2>/dev/null
  66. fi
  67. start_time=$(date +%s%N)
  68. dd if="$test_file" of=/dev/null bs="$block_size" 2>/dev/null
  69. end_time=$(date +%s%N)
  70. fi
  71. duration_ms=$(((end_time - start_time) / 1000000))
  72. throughput_mbps=$(bc <<< "scale=2; $file_size_mb * 1000 / $duration_ms")
  73. # Save results
  74. cat > "$result_file" << EOF
  75. {
  76. "test_name": "$test_name",
  77. "operation": "$operation",
  78. "file_size_mb": $file_size_mb,
  79. "block_size": "$block_size",
  80. "duration_ms": $duration_ms,
  81. "throughput_mbps": $throughput_mbps,
  82. "timestamp": "$(date -Iseconds)"
  83. }
  84. EOF
  85. echo " Duration: ${duration_ms}ms"
  86. echo " Throughput: ${throughput_mbps} MB/s"
  87. echo ""
  88. # Cleanup write test files
  89. if [[ "$operation" == "write" ]]; then
  90. rm -f "$test_file"
  91. fi
  92. }
  93. # Function to run FIO performance test
  94. run_fio_test() {
  95. local test_name=$1
  96. local rw_type=$2 # "read", "write", "randread", "randwrite"
  97. local block_size=$3
  98. local file_size=$4
  99. local iodepth=$5
  100. local test_file="$MOUNT_POINT/fio_test_${test_name}.dat"
  101. local result_file="$PERFORMANCE_RESULTS_DIR/fio_${test_name}.json"
  102. echo -e "${BLUE}🔬 Running FIO test: $test_name${NC}"
  103. echo " Type: $rw_type, Block Size: $block_size, File Size: $file_size, IO Depth: $iodepth"
  104. # Run FIO test
  105. fio --name="$test_name" \
  106. --filename="$test_file" \
  107. --rw="$rw_type" \
  108. --bs="$block_size" \
  109. --size="$file_size" \
  110. --iodepth="$iodepth" \
  111. --direct=1 \
  112. --runtime=30 \
  113. --time_based \
  114. --group_reporting \
  115. --output-format=json \
  116. --output="$result_file" \
  117. 2>/dev/null
  118. # Extract key metrics
  119. if [[ -f "$result_file" ]]; then
  120. local iops throughput_kbps latency_us
  121. iops=$(jq -r '.jobs[0].'"$rw_type"'.iops // 0' "$result_file" 2>/dev/null || echo "0")
  122. throughput_kbps=$(jq -r '.jobs[0].'"$rw_type"'.bw // 0' "$result_file" 2>/dev/null || echo "0")
  123. latency_us=$(jq -r '.jobs[0].'"$rw_type"'.lat_ns.mean // 0' "$result_file" 2>/dev/null || echo "0")
  124. latency_us=$(bc <<< "scale=2; $latency_us / 1000" 2>/dev/null || echo "0")
  125. echo " IOPS: $iops"
  126. echo " Throughput: $(bc <<< "scale=2; $throughput_kbps / 1024") MB/s"
  127. echo " Average Latency: ${latency_us} μs"
  128. else
  129. echo " FIO test failed or no results"
  130. fi
  131. echo ""
  132. # Cleanup
  133. rm -f "$test_file"
  134. }
  135. # Function to run concurrent access test
  136. run_concurrent_test() {
  137. local num_processes=$1
  138. local file_size_mb=$2
  139. echo -e "${BLUE}🔬 Running concurrent access test${NC}"
  140. echo " Processes: $num_processes, File Size per Process: ${file_size_mb}MB"
  141. local start_time end_time duration_ms total_throughput
  142. local pids=()
  143. start_time=$(date +%s%N)
  144. # Start concurrent processes
  145. for i in $(seq 1 "$num_processes"); do
  146. (
  147. local test_file="$MOUNT_POINT/concurrent_test_$i.dat"
  148. dd if=/dev/zero of="$test_file" bs=1M count="$file_size_mb" 2>/dev/null
  149. dd if="$test_file" of=/dev/null bs=1M 2>/dev/null
  150. rm -f "$test_file"
  151. ) &
  152. pids+=($!)
  153. done
  154. # Wait for all processes to complete
  155. for pid in "${pids[@]}"; do
  156. wait "$pid"
  157. done
  158. end_time=$(date +%s%N)
  159. duration_ms=$(((end_time - start_time) / 1000000))
  160. total_throughput=$(bc <<< "scale=2; $num_processes * $file_size_mb * 2 * 1000 / $duration_ms")
  161. # Save results
  162. cat > "$PERFORMANCE_RESULTS_DIR/concurrent_test.json" << EOF
  163. {
  164. "test_name": "concurrent_access",
  165. "num_processes": $num_processes,
  166. "file_size_mb_per_process": $file_size_mb,
  167. "total_data_mb": $((num_processes * file_size_mb * 2)),
  168. "duration_ms": $duration_ms,
  169. "total_throughput_mbps": $total_throughput,
  170. "timestamp": "$(date -Iseconds)"
  171. }
  172. EOF
  173. echo " Duration: ${duration_ms}ms"
  174. echo " Total Throughput: ${total_throughput} MB/s"
  175. echo ""
  176. }
  177. # Function to generate performance report
  178. generate_report() {
  179. local report_file="$PERFORMANCE_RESULTS_DIR/performance_report.html"
  180. echo -e "${BLUE}📊 Generating performance report...${NC}"
  181. cat > "$report_file" << 'EOF'
  182. <!DOCTYPE html>
  183. <html>
  184. <head>
  185. <title>SeaweedFS RDMA Mount Performance Report</title>
  186. <style>
  187. body { font-family: Arial, sans-serif; margin: 20px; }
  188. .header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
  189. .test-section { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
  190. .metric { margin: 5px 0; }
  191. .good { color: green; font-weight: bold; }
  192. .warning { color: orange; font-weight: bold; }
  193. .error { color: red; font-weight: bold; }
  194. table { border-collapse: collapse; width: 100%; }
  195. th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
  196. th { background-color: #f2f2f2; }
  197. </style>
  198. </head>
  199. <body>
  200. <div class="header">
  201. <h1>🏁 SeaweedFS RDMA Mount Performance Report</h1>
  202. <p>Generated: $(date)</p>
  203. <p>Mount Point: $MOUNT_POINT</p>
  204. <p>RDMA Sidecar: $RDMA_SIDECAR_ADDR</p>
  205. </div>
  206. EOF
  207. # Add DD test results
  208. echo '<div class="test-section"><h2>DD Performance Tests</h2><table><tr><th>Test</th><th>Operation</th><th>Size</th><th>Block Size</th><th>Throughput (MB/s)</th><th>Duration (ms)</th></tr>' >> "$report_file"
  209. for result_file in "$PERFORMANCE_RESULTS_DIR"/dd_*.json; do
  210. if [[ -f "$result_file" ]]; then
  211. local test_name operation file_size_mb block_size throughput_mbps duration_ms
  212. test_name=$(jq -r '.test_name' "$result_file" 2>/dev/null || echo "unknown")
  213. operation=$(jq -r '.operation' "$result_file" 2>/dev/null || echo "unknown")
  214. file_size_mb=$(jq -r '.file_size_mb' "$result_file" 2>/dev/null || echo "0")
  215. block_size=$(jq -r '.block_size' "$result_file" 2>/dev/null || echo "unknown")
  216. throughput_mbps=$(jq -r '.throughput_mbps' "$result_file" 2>/dev/null || echo "0")
  217. duration_ms=$(jq -r '.duration_ms' "$result_file" 2>/dev/null || echo "0")
  218. echo "<tr><td>$test_name</td><td>$operation</td><td>${file_size_mb}MB</td><td>$block_size</td><td>$throughput_mbps</td><td>$duration_ms</td></tr>" >> "$report_file"
  219. fi
  220. done
  221. echo '</table></div>' >> "$report_file"
  222. # Add FIO test results
  223. echo '<div class="test-section"><h2>FIO Performance Tests</h2>' >> "$report_file"
  224. echo '<p>Detailed FIO results are available in individual JSON files.</p></div>' >> "$report_file"
  225. # Add concurrent test results
  226. if [[ -f "$PERFORMANCE_RESULTS_DIR/concurrent_test.json" ]]; then
  227. echo '<div class="test-section"><h2>Concurrent Access Test</h2>' >> "$report_file"
  228. local num_processes total_throughput duration_ms
  229. num_processes=$(jq -r '.num_processes' "$PERFORMANCE_RESULTS_DIR/concurrent_test.json" 2>/dev/null || echo "0")
  230. total_throughput=$(jq -r '.total_throughput_mbps' "$PERFORMANCE_RESULTS_DIR/concurrent_test.json" 2>/dev/null || echo "0")
  231. duration_ms=$(jq -r '.duration_ms' "$PERFORMANCE_RESULTS_DIR/concurrent_test.json" 2>/dev/null || echo "0")
  232. echo "<p>Processes: $num_processes</p>" >> "$report_file"
  233. echo "<p>Total Throughput: $total_throughput MB/s</p>" >> "$report_file"
  234. echo "<p>Duration: $duration_ms ms</p>" >> "$report_file"
  235. echo '</div>' >> "$report_file"
  236. fi
  237. echo '</body></html>' >> "$report_file"
  238. echo " Report saved to: $report_file"
  239. }
  240. # Main test execution
  241. main() {
  242. echo -e "${BLUE}🚀 Starting performance tests...${NC}"
  243. echo ""
  244. # Wait for mount to be ready
  245. if ! wait_for_mount; then
  246. echo -e "${RED}❌ Mount is not ready, aborting tests${NC}"
  247. exit 1
  248. fi
  249. # Get initial RDMA stats
  250. echo -e "${BLUE}📊 Initial RDMA Statistics:${NC}"
  251. get_rdma_stats | jq . 2>/dev/null || get_rdma_stats
  252. echo ""
  253. # Run DD performance tests
  254. echo -e "${BLUE}🏃 Running DD Performance Tests...${NC}"
  255. run_dd_test "small_write" 10 "4k" "write"
  256. run_dd_test "small_read" 10 "4k" "read"
  257. run_dd_test "medium_write" 100 "64k" "write"
  258. run_dd_test "medium_read" 100 "64k" "read"
  259. run_dd_test "large_write" 500 "1M" "write"
  260. run_dd_test "large_read" 500 "1M" "read"
  261. # Run FIO performance tests
  262. echo -e "${BLUE}🏃 Running FIO Performance Tests...${NC}"
  263. run_fio_test "seq_read" "read" "64k" "100M" 1
  264. run_fio_test "seq_write" "write" "64k" "100M" 1
  265. run_fio_test "rand_read" "randread" "4k" "100M" 16
  266. run_fio_test "rand_write" "randwrite" "4k" "100M" 16
  267. # Run concurrent access test
  268. echo -e "${BLUE}🏃 Running Concurrent Access Test...${NC}"
  269. run_concurrent_test 4 50
  270. # Get final RDMA stats
  271. echo -e "${BLUE}📊 Final RDMA Statistics:${NC}"
  272. get_rdma_stats | jq . 2>/dev/null || get_rdma_stats
  273. echo ""
  274. # Generate performance report
  275. generate_report
  276. echo -e "${GREEN}🎉 Performance tests completed!${NC}"
  277. echo "Results saved to: $PERFORMANCE_RESULTS_DIR"
  278. }
  279. # Run main function
  280. main "$@"