def run_tests(self, experiment, run): exp = experiment(self.run_f) pg_ctl = local[path.join(self.builddir, "pg_ctl")] dropdb = local[path.join(self.builddir, "dropdb")] createdb = local[path.join(self.builddir, "createdb")] pgbench = local[path.join(self.builddir, "pgbench")] bin_name = path.join(self.builddir, self.name + ".sh") test_data = path.join(self.testdir, "test-data") (echo["#!/bin/sh"] >> bin_name)() (echo[str(exp)] >> bin_name)() chmod("+x", bin_name) num_clients = 1 num_transactions = 1000000 pg_ctl("stop", "-t", 360, "-w", "-D", test_data, retcode=None) try: with local.cwd(test_data): pg_ctl("start", "-p", bin_name, "-w", "-D", test_data) dropdb["pgbench"] & FG(retcode=None) createdb("pgbench") run(pgbench["-i", "pgbench"]) run(pgbench["-c", num_clients, "-S", "-t", num_transactions, "pgbench"]) dropdb("pgbench") pg_ctl("stop", "-t", 360, "-w", "-D", test_data) except Exception: pg_ctl("stop", "-t", 360, "-w", "-D", test_data) raise
def wrap_dynamic(project, name, sprefix=None, python=sys.executable, name_filters=None): """ Wrap the binary :name with the function :runner. This module generates a python tool :name: that can replace a yet unspecified binary. It behaves similar to the :wrap: function. However, the first argument is the actual binary name. Args: name: name of the python module runner: Function that should run the real binary sprefix: Prefix that should be used for commands. python: The python executable that should be used. name_filters: List of regex expressions that are used to filter the real project name. Make sure to include a match group named 'name' in the regex, e.g., [ r'foo(?P<name>.)-flt' ] Returns: plumbum command, readty to launch. """ from jinja2 import Environment, PackageLoader env = Environment(trim_blocks=True, lstrip_blocks=True, loader=PackageLoader('benchbuild', 'utils/templates')) template = env.get_template('run_dynamic.py.inc') name_absolute = os.path.abspath(name) real_f = name_absolute + PROJECT_BIN_F_EXT project_file = persist(project, suffix=".project") bin_path = list_to_path(CFG["env"]["path"].value()) bin_path = list_to_path([bin_path, os.environ["PATH"]]) bin_lib_path = \ list_to_path(CFG["env"]["ld_library_path"].value()) bin_lib_path = \ list_to_path([bin_lib_path, os.environ["LD_LIBRARY_PATH"]]) with open(name_absolute, 'w') as wrapper: wrapper.write( template.render(runf=strip_path_prefix(real_f, sprefix), project_file=strip_path_prefix( project_file, sprefix), path=str(bin_path), ld_library_path=str(bin_lib_path), python=python, name_filters=name_filters)) chmod("+x", name_absolute) return local[name_absolute]
def wrap_dynamic(project, name, sprefix=None, python=sys.executable, name_filters=None): """ Wrap the binary :name with the function :runner. This module generates a python tool :name: that can replace a yet unspecified binary. It behaves similar to the :wrap: function. However, the first argument is the actual binary name. Args: name: name of the python module runner: Function that should run the real binary sprefix: Prefix that should be used for commands. python: The python executable that should be used. name_filters: List of regex expressions that are used to filter the real project name. Make sure to include a match group named 'name' in the regex, e.g., [ r'foo(?P<name>.)-flt' ] Returns: plumbum command, readty to launch. """ env = __create_jinja_env() template = env.get_template('run_dynamic.py.inc') name_absolute = os.path.abspath(name) real_f = name_absolute + PROJECT_BIN_F_EXT project_file = persist(project, suffix=".project") env = CFG['env'].value bin_path = list_to_path(env.get('PATH', [])) bin_path = list_to_path([bin_path, os.environ["PATH"]]) bin_lib_path = \ list_to_path(env.get('LD_LIBRARY_PATH', [])) bin_lib_path = \ list_to_path([bin_lib_path, os.environ["LD_LIBRARY_PATH"]]) with open(name_absolute, 'w') as wrapper: wrapper.write( template.render( runf=strip_path_prefix(real_f, sprefix), project_file=strip_path_prefix(project_file, sprefix), path=str(bin_path), ld_library_path=str(bin_lib_path), python=python, name_filters=name_filters)) chmod("+x", name_absolute) return local[name_absolute]
def wrap_dynamic(self, name, runner, sprefix=None, **template_vars): """ Wrap the binary :name with the function :runner. This module generates a python tool :name: that can replace a yet unspecified binary. It behaves similar to the :wrap: function. However, the first argument is the actual binary name. Args: name: name of the python module runner: Function that should run the real binary base_class: The base_class of our project. base_module: The module of base_class. Returns: plumbum command, readty to launch. """ base_class = self.__class__.__name__ base_module = self.__module__ name_absolute = os.path.abspath(name) blob_f = name_absolute + PROJECT_BLOB_F_EXT real_f = name_absolute + PROJECT_BIN_F_EXT with open(blob_f, 'wb') as blob: blob.write(dill.dumps(runner)) bin_path = list_to_path(CFG["env"]["binary_path"].value()) bin_path = list_to_path([bin_path, os.environ["PATH"]]) bin_lib_path = list_to_path(CFG["env"]["binary_ld_library_path"].value()) bin_lib_path = list_to_path([bin_lib_path, os.environ["LD_LIBRARY_PATH"]]) template_vars['db_host'] = str(CFG["db"]["host"]) template_vars['db_name'] = str(CFG["db"]["name"]) template_vars['db_port'] = str(CFG["db"]["port"]) template_vars['db_pass'] = str(CFG["db"]["pass"]) template_vars['db_user'] = str(CFG["db"]["user"]) template_vars['path'] = bin_path template_vars['ld_lib_path'] = bin_lib_path template_vars['blobf'] = strip_path_prefix(blob_f, sprefix) template_vars['runf'] = strip_path_prefix(real_f, sprefix) template_vars['base_class'] = base_class template_vars['base_module'] = base_module if 'python' not in template_vars: template_vars['python'] = sys.executable with open(name_absolute, 'w') as wrapper: lines = template_str("templates/run_dynamic.py.inc") lines = lines.format(**template_vars) wrapper.write(lines) chmod("+x", name_absolute) return local[name_absolute]
def __save__(script_name, benchbuild, experiment, projects): """ Dump a bash script that can be given to SLURM. Args: script_name (str): name of the bash script. commands (list(benchbuild.utils.cmd)): List of plumbum commands to write to the bash script. **kwargs: Dictionary with all environment variable bindings we should map in the bash script. """ from jinja2 import Environment, PackageLoader logs_dir = os.path.dirname(CFG['slurm']['logs'].value) node_command = str(benchbuild["-E", experiment.name, "$_project"]) env = Environment( trim_blocks=True, lstrip_blocks=True, loader=PackageLoader('benchbuild', 'utils/templates')) template = env.get_template('slurm.sh.inc') with open(script_name, 'w') as slurm2: slurm2.write( template.render( config=["export " + x for x in repr(CFG).split('\n')], clean_lockdir=str(CFG["slurm"]["node_dir"]), clean_lockfile=str(CFG["slurm"]["node_dir"]) + \ ".clean-in-progress.lock", cpus=int(CFG['slurm']['cpus_per_task']), exclusive=bool(CFG['slurm']['exclusive']), lockfile=str(CFG['slurm']["node_dir"]) + ".lock", log=local.path(logs_dir) / str(experiment.id), max_running=int(CFG['slurm']['max_running']), name=experiment.name, nice=int(CFG['slurm']['nice']), nice_clean=int(CFG["slurm"]["nice_clean"]), node_command=node_command, no_multithreading=not CFG['slurm']['multithread'], ntasks=1, prefix=str(CFG["slurm"]["node_dir"]), projects=projects, slurm_account=str(CFG["slurm"]["account"]), slurm_partition=str(CFG["slurm"]["partition"]), timelimit=str(CFG['slurm']['timelimit']), ) ) chmod("+x", script_name) if not __verify__(script_name): LOG.error("SLURM script failed verification.") print("SLURM script written to {0}".format(script_name)) return script_name
def __save__(script_name, benchbuild, experiment, projects): """ Dump a bash script that can be given to SLURM. Args: script_name (str): name of the bash script. commands (list(benchbuild.utils.cmd)): List of plumbum commands to write to the bash script. **kwargs: Dictionary with all environment variable bindings we should map in the bash script. """ from jinja2 import Environment, PackageLoader logs_dir = os.path.dirname(CFG['slurm']['logs'].value) node_command = str(benchbuild["-E", experiment.name, "$_project"]) env = Environment(trim_blocks=True, lstrip_blocks=True, loader=PackageLoader('benchbuild', 'utils/templates')) template = env.get_template('slurm.sh.inc') with open(script_name, 'w') as slurm2: slurm2.write( template.render( config=["export " + x for x in repr(CFG).split('\n')], clean_lockdir=str(CFG["slurm"]["node_dir"]), clean_lockfile=str(CFG["slurm"]["node_dir"]) + \ ".clean-in-progress.lock", cpus=int(CFG['slurm']['cpus_per_task']), exclusive=bool(CFG['slurm']['exclusive']), lockfile=str(CFG['slurm']["node_dir"]) + ".lock", log=local.path(logs_dir) / str(experiment.id), max_running=int(CFG['slurm']['max_running']), name=experiment.name, nice=int(CFG['slurm']['nice']), nice_clean=int(CFG["slurm"]["nice_clean"]), node_command=node_command, no_multithreading=not CFG['slurm']['multithread'], ntasks=1, prefix=str(CFG["slurm"]["node_dir"]), projects=projects, slurm_account=str(CFG["slurm"]["account"]), slurm_partition=str(CFG["slurm"]["partition"]), timelimit=str(CFG['slurm']['timelimit']), ) ) chmod("+x", script_name) if not __verify__(script_name): LOG.error("SLURM script failed verification.") print("SLURM script written to {0}".format(script_name)) return script_name
def wrap_cc(filepath, compiler, project, python=sys.executable, detect_project=False): """ Substitute a compiler with a script that hides CFLAGS & LDFLAGS. This will generate a wrapper script in the current directory and return a complete plumbum command to it. Args: filepath (str): Path to the wrapper script. compiler (benchbuild.utils.cmd): Real compiler command we should call in the script. project (benchbuild.project.Project): The project this compiler will be for. python (str): Path to the python interpreter we should use. detect_project: Should we enable project detection or not. Returns (benchbuild.utils.cmd): Command of the new compiler we can call. """ env = __create_jinja_env() template = env.get_template('run_compiler.py.inc') cc_fname = local.path(filepath).with_suffix(".benchbuild.cc", depth=0) cc_f = persist(compiler, filename=cc_fname) project_file = persist(project, suffix=".project") with open(filepath, 'w') as wrapper: wrapper.write( template.render( cc_f=cc_f, project_file=project_file, python=python, detect_project=detect_project)) chmod("+x", filepath) LOG.debug("Placed wrapper in: %s for compiler %s", local.path(filepath), str(compiler)) LOG.debug("Placed project in: %s", local.path(project_file)) LOG.debug("Placed compiler command in: %s", local.path(cc_f)) return local[filepath]
def wrap_cc(filepath, compiler, project, compiler_ext_name=None, python=sys.executable, detect_project=False): """ Substitute a compiler with a script that hides CFLAGS & LDFLAGS. This will generate a wrapper script in the current directory and return a complete plumbum command to it. Args: filepath (str): Path to the wrapper script. compiler (benchbuild.utils.cmd): Real compiler command we should call in the script. project (benchbuild.project.Project): The project this compiler will be for. experiment (benchbuild.experiment.Experiment): The experiment this compiler will be for. extension: A function that will be pickled alongside the compiler. It will be called before the actual compilation took place. This way you can intercept the compilation process with arbitrary python code. compiler_ext_name: The name that we should give to the generated dill blob for :func: detect_project: Should we enable project detection or not. Returns (benchbuild.utils.cmd): Command of the new compiler we can call. """ from jinja2 import Environment, PackageLoader env = Environment(trim_blocks=True, lstrip_blocks=True, loader=PackageLoader('benchbuild', 'utils/templates')) template = env.get_template('run_compiler.py.inc') cc_f = persist(compiler(), filename=os.path.abspath(filepath + ".benchbuild.cc")) project_file = persist(project, suffix=".project") #experiment_file = persist(experiment, suffix=".experiment") # Change name if necessary (UCHROOT support, host <-> guest). if compiler_ext_name is not None: project_file = compiler_ext_name(".project") #experiment_file = compiler_ext_name(".experiment") cc_f = compiler_ext_name(".benchbuild.cc") # Update LDFLAGS with configure ld_library_path. This way # the libraries found in LD_LIBRARY_PATH are available at link-time too. #lib_path_list = CFG["env"]["ld_library_path"].value() #ldflags = ldflags + ["-L" + pelem for pelem in lib_path_list if pelem] with open(filepath, 'w') as wrapper: wrapper.write( template.render( cc_f=cc_f, project_file=project_file, #experiment_file=experiment_file, python=python, detect_project=detect_project)) chmod("+x", filepath) LOG.debug("Placed wrapper in: {wrapper} for compiler {compiler}".format( wrapper=os.path.abspath(filepath), compiler=compiler())) return local[filepath]
def wrap_cc(filepath, cflags, ldflags, compiler, extension, compiler_ext_name=None, **template_vars): """ Substitute a compiler with a script that hides CFLAGS & LDFLAGS. This will generate a wrapper script in the current directory and return a complete plumbum command to it. Args: filepath (str): Path to the wrapper script. cflags (list(str)): The CFLAGS we want to hide. ldflags (list(str)): The LDFLAGS we want to hide. compiler (benchbuild.utils.cmd): Real compiler command we should call in the script. extension: A function that will be pickled alongside the compiler. It will be called before the actual compilation took place. This way you can intercept the compilation process with arbitrary python code. compiler_ext_name: The name that we should give to the generated dill blob for :func: Returns (benchbuild.utils.cmd): Command of the new compiler we can call. """ cc_f = os.path.abspath(filepath + ".benchbuild.cc") with open(cc_f, 'wb') as cc: cc.write(dill.dumps(compiler())) if compiler_ext_name is not None: cc_f = compiler_ext_name(".benchbuild.cc") blob_f = os.path.abspath(filepath + PROJECT_BLOB_F_EXT) if extension is not None: with open(blob_f, 'wb') as blob: blob.write(dill.dumps(extension)) if compiler_ext_name is not None: blob_f = compiler_ext_name(PROJECT_BLOB_F_EXT) # Update LDFLAGS with configure compiler_ld_library_path. This way # the libraries found in LD_LIBRARY_PATH are available at link-time too. lib_path_list = CFG["env"]["compiler_ld_library_path"].value() ldflags = ldflags + ["-L" + pelem for pelem in lib_path_list if pelem] template_vars['db_host'] = str(CFG["db"]["host"]) template_vars['db_name'] = str(CFG["db"]["name"]) template_vars['db_port'] = str(CFG["db"]["port"]) template_vars['db_pass'] = str(CFG["db"]["pass"]) template_vars['db_user'] = str(CFG["db"]["user"]) template_vars['CFG_FILE'] = CFG["config_file"].value() template_vars['CC_F'] = cc_f template_vars['CFLAGS'] = cflags template_vars['LDFLAGS'] = ldflags template_vars['BLOB_F'] = blob_f if 'python' not in template_vars: template_vars['python'] = sys.executable with open(filepath, 'w') as wrapper: lines = template_str("templates/compiler.py.inc") lines = lines.format(**template_vars) wrapper.write(lines) chmod("+x", filepath)
def dump_slurm_script(script_name, benchbuild, experiment, projects): """ Dump a bash script that can be given to SLURM. Args: script_name (str): name of the bash script. commands (list(benchbuild.utils.cmd)): List of plumbum commands to write to the bash script. **kwargs: Dictionary with all environment variable bindings we should map in the bash script. """ log_path = os.path.join(CFG['slurm']['logs'].value()) max_running_jobs = CFG['slurm']['max_running'].value() with open(script_name, 'w') as slurm: lines = """#!/bin/bash #SBATCH -o /dev/null #SBATCH -t \"{timelimit}\" #SBATCH --ntasks 1 #SBATCH --cpus-per-task {cpus} """ slurm.write(lines.format(log=str(log_path), timelimit=str(CFG['slurm']['timelimit']), cpus=str(CFG['slurm']['cpus_per_task']))) if not CFG['slurm']['multithread'].value(): slurm.write("#SBATCH --hint=nomultithread\n") if CFG['slurm']['exclusive'].value(): slurm.write("#SBATCH --exclusive\n") slurm.write("#SBATCH --array=0-{0}".format(len(projects) - 1)) slurm.write("%{0}\n".format(max_running_jobs) if max_running_jobs > 0 else '\n') slurm.write("#SBATCH --nice={0}\n".format( CFG["slurm"]["nice"].value())) slurm.write("projects=(\n") for project in projects: slurm.write("'{0}'\n".format(str(project))) slurm.write(")\n") slurm.write("_project=\"${projects[$SLURM_ARRAY_TASK_ID]}\"\n") slurm_log_path = os.path.join( os.path.dirname(CFG['slurm']['logs'].value()), str(CFG['experiment_id'].value()) + '-$_project') slurm.write("exec 1> {log}\n".format(log=slurm_log_path)) slurm.write("exec 2>&1\n") slurm.write(__prepare_node_commands(experiment)) slurm.write("\n") cfg_vars = repr(CFG).split('\n') cfg_vars = "\nexport ".join(cfg_vars) slurm.write("export ") slurm.write(cfg_vars) slurm.write("\n") slurm.write("scontrol update JobId=${SLURM_ARRAY_JOB_ID}_${SLURM_ARRAY_TASK_ID} ") slurm.write("JobName=\"{0} $_project\"\n".format(experiment)) slurm.write("\n") slurm.write("srun -c 1 hostname\n") # Write the experiment command. extra_logs = CFG["slurm"]["extra_log"].value() slurm.write(__cleanup_node_commands(slurm_log_path)) slurm.write("srun -c 1 rm -f {0}\n".format(extra_logs)) slurm.write( str(benchbuild["-P", "$_project", "-E", experiment]) + "\n") # Append the polyjit log to the slurm log. slurm.write("srun -c 1 cat {0}\n".format(extra_logs)) bash("-n", script_name) chmod("+x", script_name)