Skip to content

Commit f0aaccf

Browse files
committed
bench: update graph parameters and add error handling for Elixir and Erlang implementations
1 parent 6a60025 commit f0aaccf

File tree

2 files changed

+62
-28
lines changed

2 files changed

+62
-28
lines changed

bench/params_1000x.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
graphs:
2-
# ~2.56M nodes, ~10.2M directed edges; stresses memory/CPU without ER's O(n^2) generator
3-
- { type: grid, rows: 1600, cols: 1600 }
4-
# ~1.0M nodes, ~5M edges (m ~ 5); BA generator is linear in edges
5-
- { type: ba, n: 1000000, m0: 5, m: 5 }
6-
bounds: [100, 200, 400, 800]
2+
# ~100k nodes, ~0.4M directed edges
3+
- { type: grid, rows: 320, cols: 320 }
4+
# ~200k nodes, ~1M edges (m ~ 5)
5+
- { type: ba, n: 200000, m0: 5, m: 5 }
6+
bounds: [50, 100, 200, 400]
77
sources_k: [4, 16]
8-
trials: 3
8+
trials: 1
99
seed: 42
1010
maxw: 100
11-
threads: [32]
11+
threads: [1, 16]

bench/runner.py

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,17 @@ def build_elixir(root):
291291

292292
def run_elixir(exs_path, graph_cfg, B, k, trials, seed, maxw, timeout_s=0):
293293
gtype = graph_cfg['type']
294+
if gtype == 'ba':
295+
# Elixir implementation currently lacks BA support; skip to avoid hard failures
296+
print(f"[info] Elixir impl does not support graph type \"{gtype}\" yet; skipping", file=sys.stderr)
297+
return []
294298
args = ['elixir', str(exs_path), '--trials', str(trials), '--k', str(k), '--B', str(B), '--seed', str(seed), '--maxw', str(maxw), '--graph', gtype]
295299
if gtype == 'grid':
296300
args += ['--rows', str(graph_cfg['rows']), '--cols', str(graph_cfg['cols'])]
297301
elif gtype == 'er':
298302
args += ['--n', str(graph_cfg['n']), '--p', str(graph_cfg['p'])]
299303
elif gtype == 'ba':
304+
# See above early return; keep branch for completeness if support is added later
300305
args += ['--n', str(graph_cfg['n']), '--m0', str(graph_cfg.get('m0',5)), '--m', str(graph_cfg.get('m',5))]
301306
else:
302307
return []
@@ -305,6 +310,9 @@ def run_elixir(exs_path, graph_cfg, B, k, trials, seed, maxw, timeout_s=0):
305310
except subprocess.TimeoutExpired:
306311
print(f'[warn] elixir run timed out: {args}', file=sys.stderr)
307312
return []
313+
except subprocess.CalledProcessError as e:
314+
print(f'[warn] elixir run failed (exit {e.returncode}); skipping: {args}', file=sys.stderr)
315+
return []
308316
rows = [json.loads(line) for line in p.stdout.splitlines() if line.strip()]
309317
for r in rows:
310318
r['graph_cfg'] = graph_cfg
@@ -320,6 +328,9 @@ def build_erlang(root):
320328

321329
def run_erlang(beam_path, graph_cfg, B, k, trials, seed, maxw, timeout_s=0):
322330
gtype = graph_cfg['type']
331+
if gtype == 'ba':
332+
print(f"[info] Erlang impl does not support graph type \"{gtype}\" yet; skipping", file=sys.stderr)
333+
return []
323334
args = ['erl', '-noshell', '-pa', str(beam_path.parent), '-s', 'bmssp', 'main', '-s', 'init', 'stop', '-extra', '--trials', str(trials), '--k', str(k), '--B', str(B), '--seed', str(seed), '--maxw', str(maxw), '--graph', gtype]
324335
if gtype == 'grid':
325336
args += ['--rows', str(graph_cfg['rows']), '--cols', str(graph_cfg['cols'])]
@@ -334,6 +345,9 @@ def run_erlang(beam_path, graph_cfg, B, k, trials, seed, maxw, timeout_s=0):
334345
except subprocess.TimeoutExpired:
335346
print(f'[warn] erlang run timed out: {args}', file=sys.stderr)
336347
return []
348+
except subprocess.CalledProcessError as e:
349+
print(f'[warn] erlang run failed (exit {e.returncode}); skipping: {args}', file=sys.stderr)
350+
return []
337351
rows = [json.loads(line) for line in p.stdout.splitlines() if line.strip()]
338352
for r in rows:
339353
r['graph_cfg'] = graph_cfg
@@ -395,6 +409,8 @@ def main():
395409
ap.add_argument('--smoke', action='store_true', help='use bench/smoke_matrix.yaml and enforce basic invariants')
396410
ap.add_argument('--parity', action='store_true', help='check simple cross-impl parity on grid graphs')
397411
ap.add_argument('--shared-inputs', action='store_true', help='use canonical shared graph+sources files for supported implementations')
412+
ap.add_argument('--include-impls', default='', help='comma-separated list of impl keys to include (rust,c,cpp,kotlin,crystal,elixir,erlang,nim)')
413+
ap.add_argument('--exclude-impls', default='', help='comma-separated list of impl keys to exclude')
398414
args = ap.parse_args()
399415

400416
# build
@@ -405,39 +421,52 @@ def main():
405421
subprocess.run(['cargo', 'build', '-p', 'bmssp'], cwd=ROOT, check=True)
406422
rust_bin = ROOT / 'target' / 'debug' / 'bmssp-cli'
407423

424+
# Impl filters
425+
all_keys = {'rust','c','cpp','kotlin','crystal','elixir','erlang','nim'}
426+
inc = set(x.strip() for x in args.include_impls.split(',') if x.strip()) or set(all_keys)
427+
exc = set(x.strip() for x in args.exclude_impls.split(',') if x.strip())
428+
sel = (inc & all_keys) - exc
429+
408430
crystal_bin = None
409431
try:
410-
crystal_bin = build_crystal(ROOT)
432+
if 'crystal' in sel:
433+
crystal_bin = build_crystal(ROOT)
411434
except Exception as e:
412435
print(f'[warn] crystal build skipped: {e}', file=sys.stderr)
413436
c_bin = None
414437
try:
415-
c_bin = build_c(ROOT)
438+
if 'c' in sel:
439+
c_bin = build_c(ROOT)
416440
except Exception as e:
417441
print(f'[warn] c build skipped: {e}', file=sys.stderr)
418442
cpp_bin = None
419443
try:
420-
cpp_bin = build_cpp(ROOT)
444+
if 'cpp' in sel:
445+
cpp_bin = build_cpp(ROOT)
421446
except Exception as e:
422447
print(f'[warn] cpp build skipped: {e}', file=sys.stderr)
423448
kotlin_jar = None
424449
try:
425-
kotlin_jar = build_kotlin(ROOT)
450+
if 'kotlin' in sel:
451+
kotlin_jar = build_kotlin(ROOT)
426452
except Exception as e:
427453
print(f'[warn] kotlin build skipped: {e}', file=sys.stderr)
428454
elixir_exs = None
429455
try:
430-
elixir_exs = build_elixir(ROOT)
456+
if 'elixir' in sel:
457+
elixir_exs = build_elixir(ROOT)
431458
except Exception as e:
432459
print(f'[warn] elixir build skipped: {e}', file=sys.stderr)
433460
erlang_beam = None
434461
try:
435-
erlang_beam = build_erlang(ROOT)
462+
if 'erlang' in sel:
463+
erlang_beam = build_erlang(ROOT)
436464
except Exception as e:
437465
print(f'[warn] erlang build skipped: {e}', file=sys.stderr)
438466
nim_bin = None
439467
try:
440-
nim_bin = build_nim(ROOT)
468+
if 'nim' in sel:
469+
nim_bin = build_nim(ROOT)
441470
except Exception as e:
442471
print(f'[warn] nim build skipped: {e}', file=sys.stderr)
443472

@@ -509,41 +538,46 @@ def maybe_validate_and_add(rows):
509538
for B in cfg['bounds']:
510539
for k in cfg['sources_k']:
511540
# Rust: run serially across thread counts to avoid CPU contention
512-
for th in threads_list:
513-
shared = None
514-
if args.shared_inputs:
515-
shared = generate_shared_inputs(g, k, cfg['seed'], cfg['maxw'], out_dir)
516-
rows = run_rust(g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], th, rust_bin, timeout_s=args.timeout_seconds, shared_inputs=shared)
517-
maybe_validate_and_add(rows)
541+
if 'rust' in sel:
542+
for th in threads_list:
543+
shared = None
544+
if args.shared_inputs:
545+
shared = generate_shared_inputs(g, k, cfg['seed'], cfg['maxw'], out_dir)
546+
rows = run_rust(g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], th, rust_bin, timeout_s=args.timeout_seconds, shared_inputs=shared)
547+
maybe_validate_and_add(rows)
518548

519549
# Prepare non-Rust tasks
520550
tasks = []
521-
if crystal_bin is not None:
551+
if 'crystal' in sel and crystal_bin is not None:
522552
# Crystal: no shared-input support yet
523553
tasks.append((run_crystal, (crystal_bin, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds)))
524-
if c_bin is not None:
554+
if 'c' in sel and c_bin is not None:
525555
shared = None
526556
if args.shared_inputs:
527557
shared = generate_shared_inputs(g, k, cfg['seed'], cfg['maxw'], out_dir)
528558
tasks.append((run_c, (c_bin, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds, shared)))
529-
if cpp_bin is not None:
559+
if 'cpp' in sel and cpp_bin is not None:
530560
shared = None
531561
if args.shared_inputs:
532562
shared = generate_shared_inputs(g, k, cfg['seed'], cfg['maxw'], out_dir)
533563
tasks.append((run_cpp, (cpp_bin, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds, shared)))
534-
if kotlin_jar is not None:
564+
if 'kotlin' in sel and kotlin_jar is not None:
535565
tasks.append((run_kotlin, (kotlin_jar, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds)))
536-
if elixir_exs is not None:
566+
if 'elixir' in sel and elixir_exs is not None:
537567
tasks.append((run_elixir, (elixir_exs, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds)))
538-
if erlang_beam is not None:
568+
if 'erlang' in sel and erlang_beam is not None:
539569
tasks.append((run_erlang, (erlang_beam, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds)))
540-
if nim_bin is not None:
570+
if 'nim' in sel and nim_bin is not None:
541571
tasks.append((run_nim, (nim_bin, g, B, k, cfg['trials'], cfg['seed'], cfg['maxw'], args.timeout_seconds)))
542572

543573
if tasks:
544574
if args.jobs <= 1:
545575
for func, pargs in tasks:
546-
rows = func(*pargs)
576+
try:
577+
rows = func(*pargs)
578+
except Exception as e:
579+
print(f'[warn] task failed: {e}', file=sys.stderr)
580+
rows = []
547581
maybe_validate_and_add(rows)
548582
else:
549583
with ThreadPoolExecutor(max_workers=max(1, args.jobs)) as ex:

0 commit comments

Comments
 (0)