| 29 | overhead_factor: float |
| 30 | |
| 31 | class ArrayBenchmarkRunner: |
| 32 | def __init__(self, iterations: int = 100, port: int = 15500): |
| 33 | self.iterations = iterations |
| 34 | self.port = port |
| 35 | self.sqlite_file = "array_benchmark_test.db" |
| 36 | |
| 37 | # Import psycopg3 |
| 38 | try: |
| 39 | import psycopg |
| 40 | self.psycopg = psycopg |
| 41 | except ImportError: |
| 42 | print("❌ psycopg3 not available. Install with: pip install psycopg[binary]") |
| 43 | sys.exit(1) |
| 44 | |
| 45 | self.results: List[ArrayBenchmarkResult] = [] |
| 46 | |
| 47 | def setup(self): |
| 48 | """Remove existing database file if it exists""" |
| 49 | if os.path.exists(self.sqlite_file): |
| 50 | os.remove(self.sqlite_file) |
| 51 | |
| 52 | def cleanup(self): |
| 53 | """Clean up test database""" |
| 54 | if os.path.exists(self.sqlite_file): |
| 55 | os.remove(self.sqlite_file) |
| 56 | |
| 57 | def generate_test_arrays(self, size: int) -> Dict[str, Any]: |
| 58 | """Generate test arrays of different types and sizes""" |
| 59 | return { |
| 60 | "int_array": [random.randint(1, 1000) for _ in range(size)], |
| 61 | "bigint_array": [random.randint(1000000000000, 9999999999999) for _ in range(size)], |
| 62 | "text_array": [f"text_{i}_{random.randint(1000, 9999)}" for i in range(size)], |
| 63 | "float_array": [round(random.uniform(0.0, 1000.0), 3) for _ in range(size)], |
| 64 | "bool_array": [random.choice([True, False]) for _ in range(size)] |
| 65 | } |
| 66 | |
| 67 | def measure_time(self, func, *args, **kwargs) -> float: |
| 68 | """Measure execution time of a function""" |
| 69 | start = time.perf_counter() |
| 70 | result = func(*args, **kwargs) |
| 71 | end = time.perf_counter() |
| 72 | return end - start, result |
| 73 | |
| 74 | def benchmark_sqlite_arrays(self, array_size: int) -> Dict[str, float]: |
| 75 | """Benchmark array operations using direct SQLite access""" |
| 76 | conn = sqlite3.connect(self.sqlite_file) |
| 77 | cursor = conn.cursor() |
| 78 | |
| 79 | times = {} |
| 80 | |
| 81 | # Drop and create table for clean state |
| 82 | try: |
| 83 | cursor.execute("DROP TABLE IF EXISTS array_bench_sqlite") |
| 84 | except: |
| 85 | pass |
| 86 | |
| 87 | create_time, _ = self.measure_time(cursor.execute, """ |
| 88 | CREATE TABLE array_bench_sqlite ( |
no outgoing calls