Run a single Rust benchmark and return total ops/sec.
(
project_dir: Path,
threads: int,
duration: int,
test: str,
pin: bool = False,
quiet: bool = False,
verbose: bool = False,
use_mimalloc: bool = True,
)
| 203 | |
| 204 | |
| 205 | def run_rust_benchmark( |
| 206 | project_dir: Path, |
| 207 | threads: int, |
| 208 | duration: int, |
| 209 | test: str, |
| 210 | pin: bool = False, |
| 211 | quiet: bool = False, |
| 212 | verbose: bool = False, |
| 213 | use_mimalloc: bool = True, |
| 214 | ) -> Optional[float]: |
| 215 | """Run a single Rust benchmark and return total ops/sec.""" |
| 216 | cmd = ["cargo", "bench", "--bench", "mttest"] |
| 217 | if use_mimalloc: |
| 218 | cmd.extend(["--features", "mimalloc"]) |
| 219 | cmd.extend(["--", test, f"-j{threads}", f"-d{duration}", "-t"]) |
| 220 | if pin: |
| 221 | cmd.append("-p") |
| 222 | |
| 223 | if not quiet: |
| 224 | print(f" Running Rust {test}...", end="", flush=True, file=sys.stderr) |
| 225 | |
| 226 | try: |
| 227 | timeout = duration * 3 + 60 # Extra time for compilation |
| 228 | result = subprocess.run( |
| 229 | cmd, capture_output=True, text=True, timeout=timeout, cwd=project_dir |
| 230 | ) |
| 231 | except subprocess.TimeoutExpired: |
| 232 | if not quiet: |
| 233 | print(" timeout", file=sys.stderr) |
| 234 | return None |
| 235 | except Exception as e: |
| 236 | if not quiet: |
| 237 | print(f" error: {e}", file=sys.stderr) |
| 238 | return None |
| 239 | |
| 240 | # Check for non-zero exit code (compilation failure, test crash, etc.) |
| 241 | if result.returncode != 0: |
| 242 | if not quiet: |
| 243 | print(f" exit code {result.returncode}", file=sys.stderr) |
| 244 | if verbose: |
| 245 | # Show stderr which contains compilation errors |
| 246 | print(f" stderr: {result.stderr[:1000]}", file=sys.stderr) |
| 247 | return None |
| 248 | |
| 249 | output = result.stdout |
| 250 | |
| 251 | # Parse output using regex for robustness |
| 252 | # Format: "test_name: 123.45 Mops/s" |
| 253 | for line in output.splitlines(): |
| 254 | line = line.strip() |
| 255 | match = RUST_OUTPUT_RE.match(line) |
| 256 | if match and match.group(1).lower() == test.lower(): |
| 257 | try: |
| 258 | mops = float(match.group(2)) |
| 259 | if not quiet: |
| 260 | print(f" {mops:.2f} Mops/s", file=sys.stderr) |
| 261 | # Store as integer ops/sec to avoid float precision issues |
| 262 | return int(mops * 1_000_000) |