diff --git a/scm-perf/poulpe-scheduler-bin/auto-cases b/scm-perf/poulpe-scheduler-bin/auto-cases old mode 100755 new mode 120000 index fd08c9a05eac524a75510991a2b6764a6dcced5f_c2NtLXBlcmYvcG91bHBlLXNjaGVkdWxlci1iaW4vYXV0by1jYXNlcw==..cf4d47dfbed0ec90943dbcfe834afb8dfb818db8_c2NtLXBlcmYvcG91bHBlLXNjaGVkdWxlci1iaW4vYXV0by1jYXNlcw== --- a/scm-perf/poulpe-scheduler-bin/auto-cases +++ b/scm-perf/poulpe-scheduler-bin/auto-cases @@ -1,169 +1,1 @@ -#!/usr/bin/env python3 - -from pathlib import Path -import itertools -import os -import random -import subprocess -import sys - -x = os.path.abspath(sys.argv[0]) -x = os.path.dirname(x) -x = os.path.dirname(x) -poulpe_root = os.path.dirname(x) -sys.path.insert(0, os.path.join(poulpe_root, 'python-libs')) - -import poulpe -from poulpe import benchmarks as bench_mod - -TARGET_PYTHON_VERSIONS = [ - "3.7" -] - -PY_VERSION_COMPATIBILITY = { - "3.7": 'tagged("5.2")::', -} - -FLAVOR_COMPATIBILITY = { - "rust": '(9183b7dcfa8d::)', - "rhg": '(tagged("6.1")::)', -} - - -class Case: - - def __init__( - self, - hg_hash, - hg_variant, - data_env, - benchmark, - ): - self.hg_hash = hg_hash - self.hg_variant = hg_variant - self.data_env = data_env - self.benchmark = benchmark - - def to_scheduler_line(self): - return ( - f"RUN" - f" {self.hg_hash}" - f" {self.hg_variant}" - f" {self.data_env}" - f" {self.benchmark}" - ) - -def mercurial_repository_path(base_dir): - return base_dir / "repos" / "mercurial" - -def list_mercurial_variants(base_dir, changeset): - """return a list of possible mercurial variants""" - variants = ["default", "pure"] # lets keep it simple for now - for k, v in FLAVOR_COMPATIBILITY.items(): - revs = list_mercurial_hashes(base_dir, v) - if changeset in revs: - variants.append(k) - return variants - - - -def list_mercurial_hashes(base_dir, interval="all()"): - """return a list of possible mercurial hashes""" - repo_dir = mercurial_repository_path(base_dir) - cmd = [ - "hg", - "log", - "-T", - "{node}\n", - "-R", - str(repo_dir), - "--rev", - interval, - ] - p = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf8") - return p.stdout.splitlines() - -def list_data_envs(base_dir): - """return a list of possible data_envs""" - data_dir = base_dir / "data-envs" - cmd = [ - "find", - "-L", - ".", - "-maxdepth", - "3", - "-name", - "data-env.poulpe", - ] - p = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf8", cwd=str(data_dir)) - raws = [Path(l) for l in p.stdout.splitlines()] - return [Path(*p.parts[:-1]) for p in raws] - - -compat_cache = {} - - -def compatible_with(base_dir, data_env, changeset): - """check if a data_env is compatible with the selected revision""" - path = base_dir / "data-envs" / data_env / "data-env.poulpe" - data_args = poulpe.get_data(path) - assert data_args is not None, path - ds2_key = "data-env-vars.mercurial.repo.format.dirstate-v2" - if poulpe.get_one_value(data_args, ds2_key) == "yes": - if "dirstate-v2" not in compat_cache: - revs = list_mercurial_hashes(base_dir, 'tagged("6.0")::') - compat_cache['dirstate-v2'] = set(revs) - return changeset in compat_cache['dirstate-v2'] - return True - - -def list_benchmarks(base_dir): - """return a list of possible benchmarks""" - bench_dir = base_dir / "benchmarks" - prefix = len(bench_dir.parts) - all_files = [Path(*p.parts[prefix:]) for p in bench_dir.rglob("*.pbd")] - all_benchmarks = [] - for f in all_files: - benchmark = bench_mod.get_benchmark(bench_dir / f) - all_dimensions = [] - for d, v in benchmark.all_dimensions.items(): - all_dimensions.append([f'{d}={k}' for k in list(v.keys())]) - if not all_dimensions: - all_benchmarks.append(f) - else: - for variants in itertools.product(*all_dimensions): - p = [str(f)] - p.extend(variants) - all_benchmarks.append(';'.join(p)) - return all_benchmarks - - -def main(base_dir=".", size="10"): - size = int(size) - base_dir = Path(base_dir).resolve() - for case in _main(base_dir, size): - print(case.to_scheduler_line()) - return 0 - - -def _main(base_dir, size=10): - python_version = random.choice(TARGET_PYTHON_VERSIONS) - - mercurial_intervals = PY_VERSION_COMPATIBILITY.get(python_version, "all()") - - hashes = list_mercurial_hashes(base_dir, mercurial_intervals) - datas = list_data_envs(base_dir) - benchmarks = list_benchmarks(base_dir) - for i in range(size): - h = random.choice(hashes) - variants = list_mercurial_variants(base_dir, h) - for v in variants: - for d in datas: - if not compatible_with(base_dir, d, h): - continue - for b in benchmarks: - yield Case(h, v, d, b) - - -if __name__ == "__main__": - sys.exit(main(*sys.argv[1:])) +../../suites/hg/scheduling/auto-cases \ No newline at end of file diff --git a/scm-perf/poulpe-scheduler-bin/loop b/scm-perf/poulpe-scheduler-bin/loop old mode 100755 new mode 120000 index fd08c9a05eac524a75510991a2b6764a6dcced5f_c2NtLXBlcmYvcG91bHBlLXNjaGVkdWxlci1iaW4vbG9vcA==..cf4d47dfbed0ec90943dbcfe834afb8dfb818db8_c2NtLXBlcmYvcG91bHBlLXNjaGVkdWxlci1iaW4vbG9vcA== --- a/scm-perf/poulpe-scheduler-bin/loop +++ b/scm-perf/poulpe-scheduler-bin/loop @@ -1,191 +1,1 @@ -#!/usr/bin/env python3 - -import hashlib -import json -import os -import shutil -import subprocess -import sys -import tempfile - -from pathlib import Path - -import poulpe.process_result as resultlib - -ACTION_FILE = "current.poulpe-schedule" - -RESULT_DIR = "results" -BIN_ENV_DIR = "bin-envs" -DATA_ENV_DIR = "data-envs" -BENCHMARK_DIR = "benchmarks" - -def get_first(base_dir): - return next(iter(_get_all_actions(base_dir)), None) - -def drop_first(base_dir, action): - # only overwrite if no race are detected - # (A small race windows still exists within this function) - actions = _get_all_actions(base_dir) - if actions[0] == action: - actions.pop(0) - _write_all_actions(base_dir, actions) - -def _get_all_actions(base_dir): - actions_file = base_dir / ACTION_FILE - actions = actions_file.read_text() - return [a.strip() for a in actions.splitlines()] - -def _write_all_actions(base_dir, actions): - actions_file = base_dir / ACTION_FILE - actions_file.write_text('\n'.join(actions) + '\n') - - -def process_action(base_dir, action): - parts = action.split(' ', 1) - cmd = parts[0] - if len(parts) > 1: - args = parts[1] - else: - args = '' - if cmd == "#": - pass - elif cmd == "RUN": - action_run(base_dir, *args.split()) - elif cmd == "AUTOFILL": - action_autofill(base_dir, *[int(x) for x in args.split()]) - elif cmd == "UPLOAD": - action_upload(base_dir) - else: - print("unknown action %s" % action, file=sys.stderr) - - -def action_run(base_dir, mercurial_nodeid, mercurial_variant, data_env, benchmark): - print('running:', mercurial_nodeid, mercurial_variant, data_env, benchmark) - bin_env = ensure_bin_env(base_dir, mercurial_nodeid, mercurial_variant) - if bin_env is None: - print("could not get running bin-env", file=sys.stderr) - return - - result_desc = f"{bin_env} {mercurial_variant} {data_env} {benchmark}" - result_id = hashlib.sha256(result_desc.encode("utf8")).hexdigest() - result = base_dir / RESULT_DIR / f"{result_id}.pbr" - - data_env = base_dir / DATA_ENV_DIR / data_env - benchmark = base_dir / BENCHMARK_DIR / benchmark - - run_script = base_dir / "bin/run-util" - cmd = [ - str(run_script), - str(bin_env), - str(data_env), - str(benchmark), - str(result), - ] - subprocess.call(cmd) - - -def is_ready(bin_env): - """wtf, need better""" - desc = (bin_env / "bin-env.poulpe") - if not desc.exists(): - return False - return "ready = true" in desc.read_text() - - -MAX_BIN_ENV = 50 - -def ensure_bin_env(base_dir, nodeid, variant): - bin_env_dir = base_dir / BIN_ENV_DIR - target = bin_env_dir / f"mercurial-{nodeid}-{variant}" - - all_existing = [p for p in bin_env_dir.iterdir()] - all_existing.sort(key=lambda x: x.stat().st_mtime) - - assert MAX_BIN_ENV > 1 - if len(all_existing) > MAX_BIN_ENV: - for delete_me in all_existing: - if delete_me != target: - break - print(f"Bin-envs {MAX_BIN_ENV} limit, deleting: {delete_me}") - shutil.rmtree(delete_me) - - # that check is too simple, we need to make sure this is a valid bin-env too - if target.exists() and not is_ready(target): - shutil.rmtree(target) - if not target.exists(): - setup_cmd = base_dir / "bin" / "bin-env-util" - setup_script = base_dir / "bin" / "mercurial.poulpe-setup.sh" - os.makedirs(target, exist_ok=True) - - env = os.environ.copy() - env['MERCURIAL_VERSION'] = nodeid - env['MERCURIAL_FLAVOR'] = variant - # XXX check the result of this at some point… - cmd = [ - setup_cmd, - "setup-one", - target, - setup_script, - ] - subprocess.call(cmd, env=env) - - if is_ready(target): - return target - else: - shutil.rmtree(target) - return None - - -def action_autofill(base_dir, count=None): - fill_script = base_dir / "bin/auto-cases" - cmd = [str(fill_script)] - if count: - cmd.append(str(count)) - p = subprocess.run(cmd, stdout=subprocess.PIPE, encoding="utf8") - new_actions = p.stdout.splitlines() - print("auto-fill: adding %d new actions" % len(new_actions)) - loop = ["AUTOFILL"] - if count: - loop.append(str(count)) - new_actions.append(' '.join(loop)) - # tiny race window here - actions = _get_all_actions(base_dir) - actions.extend(new_actions) - _write_all_actions(base_dir, actions) - - -def action_upload(base_dir): - results = resultlib.load_results_from_dir(base_dir / "results") - print("upload: gather and upload %d results" % len(results)) - dispatched = resultlib.group_results(results) - - with tempfile.NamedTemporaryFile(mode="w") as j: - json.dump(dispatched, j) - j.flush() - cmd = [base_dir / "bin" / "upload", j.name] - subprocess.check_call(cmd) - - # tiny race window here - actions = _get_all_actions(base_dir) - actions.append('UPLOAD') - _write_all_actions(base_dir, actions) - - -def loop(base_dir="."): - base_dir = Path(base_dir).resolve() - _loop(base_dir) - return 0 - - -def _loop(base_dir): - - action = get_first(base_dir) - while action is not None: - if action: - process_action(base_dir, action) - drop_first(base_dir, action) - action = get_first(base_dir) - - -if __name__ == "__main__": - sys.exit(loop(*sys.argv[1:])) +../../suites/hg/scheduling/loop \ No newline at end of file diff --git a/scm-perf/poulpe-scheduler-bin/auto-cases b/suites/hg/scheduling/auto-cases similarity index 100% copy from scm-perf/poulpe-scheduler-bin/auto-cases copy to suites/hg/scheduling/auto-cases diff --git a/scm-perf/poulpe-scheduler-bin/loop b/suites/hg/scheduling/loop similarity index 100% copy from scm-perf/poulpe-scheduler-bin/loop copy to suites/hg/scheduling/loop