relysqlite_benchmark.go raw

   1  package main
   2  
   3  import (
   4  	"fmt"
   5  	"log"
   6  	"os"
   7  	"path/filepath"
   8  	"time"
   9  
  10  	"next.orly.dev/pkg/database"
  11  )
  12  
  13  // RelySQLiteBenchmark wraps a Benchmark with rely-sqlite-specific setup
  14  type RelySQLiteBenchmark struct {
  15  	config   *BenchmarkConfig
  16  	database database.Database
  17  	bench    *BenchmarkAdapter
  18  	dbPath   string
  19  }
  20  
  21  // NewRelySQLiteBenchmark creates a new rely-sqlite benchmark instance
  22  func NewRelySQLiteBenchmark(config *BenchmarkConfig) (*RelySQLiteBenchmark, error) {
  23  	// Create database path
  24  	dbPath := filepath.Join(config.DataDir, "relysqlite.db")
  25  
  26  	// Ensure parent directory exists
  27  	if err := os.MkdirAll(config.DataDir, 0755); err != nil {
  28  		return nil, fmt.Errorf("failed to create data directory: %w", err)
  29  	}
  30  
  31  	// Remove existing database file if it exists
  32  	if _, err := os.Stat(dbPath); err == nil {
  33  		if err := os.Remove(dbPath); err != nil {
  34  			return nil, fmt.Errorf("failed to remove existing database: %w", err)
  35  		}
  36  	}
  37  
  38  	// Create wrapper
  39  	wrapper, err := NewRelySQLiteWrapper(dbPath)
  40  	if err != nil {
  41  		return nil, fmt.Errorf("failed to create rely-sqlite wrapper: %w", err)
  42  	}
  43  
  44  	// Wait for database to be ready
  45  	fmt.Println("Waiting for rely-sqlite database to be ready...")
  46  	select {
  47  	case <-wrapper.Ready():
  48  		fmt.Println("Rely-sqlite database is ready")
  49  	case <-time.After(10 * time.Second):
  50  		wrapper.Close()
  51  		return nil, fmt.Errorf("rely-sqlite database failed to become ready")
  52  	}
  53  
  54  	// Create adapter to use Database interface with Benchmark
  55  	adapter := NewBenchmarkAdapter(config, wrapper)
  56  
  57  	relysqliteBench := &RelySQLiteBenchmark{
  58  		config:   config,
  59  		database: wrapper,
  60  		bench:    adapter,
  61  		dbPath:   dbPath,
  62  	}
  63  
  64  	return relysqliteBench, nil
  65  }
  66  
  67  // Close closes the rely-sqlite benchmark
  68  func (rsb *RelySQLiteBenchmark) Close() {
  69  	fmt.Println("Closing rely-sqlite benchmark...")
  70  
  71  	if rsb.database != nil {
  72  		rsb.database.Close()
  73  	}
  74  
  75  	// Clean up database file
  76  	if rsb.dbPath != "" {
  77  		os.Remove(rsb.dbPath)
  78  	}
  79  }
  80  
  81  // RunSuite runs the benchmark suite on rely-sqlite
  82  func (rsb *RelySQLiteBenchmark) RunSuite() {
  83  	fmt.Println("\n╔════════════════════════════════════════════════════════╗")
  84  	fmt.Println("║       RELY-SQLITE BACKEND BENCHMARK SUITE              ║")
  85  	fmt.Println("╚════════════════════════════════════════════════════════╝")
  86  
  87  	// Run benchmark tests
  88  	fmt.Printf("\n=== Starting Rely-SQLite benchmark ===\n")
  89  
  90  	fmt.Printf("RunPeakThroughputTest (Rely-SQLite)..\n")
  91  	rsb.bench.RunPeakThroughputTest()
  92  	fmt.Println("Wiping database between tests...")
  93  	rsb.wipeDatabase()
  94  	time.Sleep(5 * time.Second)
  95  
  96  	fmt.Printf("RunBurstPatternTest (Rely-SQLite)..\n")
  97  	rsb.bench.RunBurstPatternTest()
  98  	fmt.Println("Wiping database between tests...")
  99  	rsb.wipeDatabase()
 100  	time.Sleep(5 * time.Second)
 101  
 102  	fmt.Printf("RunMixedReadWriteTest (Rely-SQLite)..\n")
 103  	rsb.bench.RunMixedReadWriteTest()
 104  	fmt.Println("Wiping database between tests...")
 105  	rsb.wipeDatabase()
 106  	time.Sleep(5 * time.Second)
 107  
 108  	fmt.Printf("RunQueryTest (Rely-SQLite)..\n")
 109  	rsb.bench.RunQueryTest()
 110  	fmt.Println("Wiping database between tests...")
 111  	rsb.wipeDatabase()
 112  	time.Sleep(5 * time.Second)
 113  
 114  	fmt.Printf("RunConcurrentQueryStoreTest (Rely-SQLite)..\n")
 115  	rsb.bench.RunConcurrentQueryStoreTest()
 116  
 117  	fmt.Printf("\n=== Rely-SQLite benchmark completed ===\n\n")
 118  }
 119  
 120  // wipeDatabase recreates the database for a clean slate
 121  func (rsb *RelySQLiteBenchmark) wipeDatabase() {
 122  	// Close existing database
 123  	if rsb.database != nil {
 124  		rsb.database.Close()
 125  	}
 126  
 127  	// Remove database file
 128  	if rsb.dbPath != "" {
 129  		os.Remove(rsb.dbPath)
 130  	}
 131  
 132  	// Recreate database
 133  	wrapper, err := NewRelySQLiteWrapper(rsb.dbPath)
 134  	if err != nil {
 135  		log.Printf("Failed to recreate database: %v", err)
 136  		return
 137  	}
 138  
 139  	rsb.database = wrapper
 140  	rsb.bench.db = wrapper
 141  }
 142  
 143  // GenerateReport generates the benchmark report
 144  func (rsb *RelySQLiteBenchmark) GenerateReport() {
 145  	rsb.bench.GenerateReport()
 146  }
 147  
 148  // GenerateAsciidocReport generates asciidoc format report
 149  func (rsb *RelySQLiteBenchmark) GenerateAsciidocReport() {
 150  	rsb.bench.GenerateAsciidocReport()
 151  }
 152