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