Experiments¶
Experiments are the base concept how the tool suite and BenchBuild execute research experiments, e.g., measuring performance or analyzing a software project.
They are designed to make the execution of research experiments easy and reproducable by separating experiment specific steps from project specific ones.
For example, how a specific project is compiled is the responsibility of the project writer, where how the project is evaluated during a research experiment is the Experiment’s task.
Note
Details on how to run experiments can be found here.
How to add a new experiment to VaRA-TS¶
Designing a new Experiment is also quite simple.
First, create a new python module in the
experimentsdirectory and add an experiment class which inherits frombenchbuild.experiment.Experiment. If VaRA-TS should provide automatic support for analyzing different versions, i.e., different revisions of a git based project, useVersionExperimentas base class.Second, define two static variables for your experiment:
NAMEandREPORT_SPECThird, your experiment needs to pass an additional
shorthandparameter.Next, override the
actions_for_projectmethod. This method should assign run-time/compile-time extensions and specify the list of actions that should be performed. Each action the experiment does is called aStepand will be executed by BenchBuild in order.Last, add your experiment for testing to the BenchBuild config file vara-root/benchbuild/.benchbuild.yml under plugins/experiments/value. After testing, integrate them into the tool suite by adding it to the experiment list in
varats.tools.bb_config.generate_benchbuild_config, so it will be automatically added to the BenchBuild config in the future.
Note
For more information about Experiment’s consider reading the BenchBuild docs.
If you’re looking for a simple example experiment, consider taking a look at JustCompileReport.
Tool suite provided experiments¶
Experiment utilities¶
WLLVM module¶
Module to provide WLLVM/GLLVM support for project compilation and extracting bc files from generated binaries.
WLLVM/GLLVM is a compiler replacement/hook to compile projects with clang, producing LLVM-IR files on the side. This allows us to hook into the build process and to add additional passes/flags, without modifying build files, and later use the generated bc files with LLVM.
- class varats.experiment.wllvm.BCFileExtensions(*values)[source]¶
Bases:
EnumList of possible extensions that specify the way a BC file was created.
An extension should be requested when a BC file needs to fulfill certain requirements, e.g., was compiled with debug metadata or compiled with optimizations.
- value: str¶
- DEBUG = 'dbg'¶
- NO_OPT = 'O0'¶
- OPT = 'O2'¶
- TBAA = 'TBAA'¶
- FEATURE = 'feature'¶
- BLAME = 'blame'¶
- BLAME_AST = 'blame_ast'¶
- class varats.experiment.wllvm.RunWLLVM(*extensions, config=None, distcc_hosts=None, **kwargs)[source]¶
Bases:
ExtensionThis extension implements the WLLVM/GLLVM compiler. GLLVM is used automatically if it is found in the PATH. Otherwise WLLVM is used.
This class is an extension that implements the WLLVM/GLLVM compiler with the required flags LLVM_COMPILER=clang and LLVM_OUTPUFILE=<path>. This compiler is used to transfer the complete project into LLVM-IR.
The distcc_hosts argument will instruct WLLVM/GLLVM to call distcc instead of clang directly. For possible values of distcc_hosts have a look at the “HOST SPECIFICATIONS” in the distcc man page. It is the user’s responsibility to ensure that all distcc hosts are configured to use exactly the same compiler as localhost!
Examples:
Usage without distcc:
RunWLLVM()Usage with distcc enabled:
RunWLLVM(distcc_hosts="localhost 192.168.1.1:3634/64")
- class varats.experiment.wllvm.Extract(project, bc_file_extensions=None, handler=None)[source]¶
Bases:
ProjectStepExtract step to extract a llvm bitcode file(.bc) from the project.
- NAME = 'EXTRACT'¶
- DESCRIPTION = 'Extract bitcode out of the execution file.'¶
- BC_CACHE_FOLDER_TEMPLATE = '{cache_dir}/{project_name}/'¶
- project: VProject¶
- varats.experiment.wllvm.project_bc_files_in_cache(project, required_bc_file_extensions)[source]¶
Checks if all bc files, corresponding to the projects binaries, are in the cache.
- Parameters:
project (
Project) – the projectrequired_bc_file_extensions (
List[BCFileExtensions] |None) – list of required file extensions
- Return type:
bool
Returns: True, if all BC files are present, False otherwise.
- varats.experiment.wllvm.get_bc_cache_actions(project, bc_file_extensions=None, extraction_error_handler=None, bc_action_creator=<function _create_default_bc_file_creation_actions>)[source]¶
Builds the action pipeline, if needed, to fill the BC file cache that provides BC files for the compiled binaries of a project.
- Parameters:
project (
Project) – the project to compilebc_file_extensions (
List[BCFileExtensions] |None) – list of bc file extensionsextraction_error_handler (
PEErrorHandler|None) – error handler to report errors during the extraction stepbc_action_creator (
Callable[[Project,List[BCFileExtensions],PEErrorHandler|None],List[Step]]) – alternative BC cache actions creation callback
- Return type:
List[Step]
Returns: required actions to populate the BC cache
- varats.experiment.wllvm.get_cached_bc_file_path(project, binary, required_bc_file_extensions=None)[source]¶
Look up the path to a BC file from the BC cache.
- Parameters:
project (
Project) – the projectbinary (
ProjectBinaryWrapper) – which corresponds to the BC filerequired_bc_file_extensions (
List[BCFileExtensions] |None) – list of required file extensions
- Return type:
Path
Returns: path to the cached BC file
Experiment utilities module¶
Utility module for BenchBuild experiments.
- varats.experiment.experiment_util.get_varats_result_folder(project)[source]
Get the project specific path to the varats result folder.
- Parameters:
project (
Project) – to lookup the result folder for- Return type:
Path- Returns:
path to the project specific result folder
- class varats.experiment.experiment_util.PEErrorHandler(result_folder, error_file_name, timeout_duration=None, delete_files=None)[source]
Bases:
objectError handler for process execution errors.
- class varats.experiment.experiment_util.FunctionPEErrorWrapper(func, handler)[source]
Bases:
objectWrap a function call with an exception handler.
- Parameters:
func (
Callable[...,Any]) – function to be executedhandler (
PEErrorHandler) – function to handle exception
- varats.experiment.experiment_util.exec_func_with_pe_error_handler(func, handler)[source]
Execute a function call with an exception handler.
- Parameters:
func (
Callable[...,Any]) – function to be executedhandler (
PEErrorHandler) – function to handle exception
- Return type:
None
- varats.experiment.experiment_util.get_default_compile_error_wrapped(experiment_handle, project, report_type)[source]
Setup the default project compile function with an error handler.
- Parameters:
experiment_handle (
ExperimentHandle) – handle to the current experimentproject (
Project) – that will be compiledreport_type (
Type[BaseReport]) – that should be generated
- Return type:
- Returns:
project compilation function, wrapped with automatic error handling
- varats.experiment.experiment_util.create_default_compiler_error_handler(experiment_handle, project, report_type, binary=None)[source]
Create a default PEErrorHandler for compile errors, based on the project, report_type.
- Parameters:
experiment_handle (
ExperimentHandle) – handle to the current experimentproject (
Project) – currently under analysisreport_type (
Type[BaseReport]) – that should be generatedbinary (
ProjectBinaryWrapper|None) – if only a specific binary is handled
- Return type:
Retruns: a initialized PEErrorHandler
- varats.experiment.experiment_util.create_default_analysis_failure_handler(experiment_handle, project, report_type, binary=None, timeout_duration=None)[source]
Create a default PEErrorHandler for analysis failures, based on the project, report_type.
- Parameters:
experiment_handle (
ExperimentHandle) – handle to the current experimentproject (
Project) – currently under analysisreport_type (
Type[BaseReport]) – that should be generatedbinary (
ProjectBinaryWrapper|None) – if only a specific binary is handledtimeout_duration (
str|None) – set timeout
- Return type:
Retruns: a initialized PEErrorHandler
- varats.experiment.experiment_util.create_default_error_handler(experiment_handle, project, report_type, error_type, binary=None, timeout_duration=None)[source]
Create a default PEErrorHandler based on the project, report_type.
- Parameters:
experiment_handle (
ExperimentHandle) – handle to the current experimentproject (
Project) – currently under analysisreport_type (
Type[BaseReport]) – that should be generatederror_type (
FileStatusExtension) – a FSE describing the problem typetimeout_duration (
str|None) – set timeoutbinary (
ProjectBinaryWrapper|None) – if only a specific binary is handled
- Return type:
Retruns: a initialized PEErrorHandler
- varats.experiment.experiment_util.wrap_unlimit_stack_size(cmd)[source]
Wraps a command with prlimit to be executed with max stack size, i.e., setting the soft limit to the hard limit.
- Parameters:
cmd (
Callable[...,Any]) – command that should be executed with max stack size- Return type:
Any
Returns: wrapped command
- class varats.experiment.experiment_util.WithUnlimitedStackSize(*extensions, **kwargs)[source]
Bases:
ExtensionSets the stack size of the wrapped command to unlimited (16GB).
- class varats.experiment.experiment_util.ExperimentHandle(experiment)[source]
Bases:
objectHandle to an experiment that provides helper interfaces for analysis steps to utilize experiment specific data.
- get_file_name(report_shorthand, project_name, binary_name, project_revision, project_uuid, extension_type, config_id=None)[source]
Generates a filename for a report file that is generated by the experiment.
- Parameters:
report_shorthand (
str) – unique shorthand for the reportproject_name (
str) – name of the project for which the report was generatedbinary_name (
str) – name of the binary for which the report was generatedproject_revision (
ShortCommitHash) – revision (commit hash)of the analyzed projectproject_uuid (
str) – benchbuild uuid for the experiment runextension_type (
FileStatusExtension) – to specify the status of the generated report
- Return type:
- Returns:
name for the report file that can later be uniquly identified
- report_spec()[source]
Experiment report specification.
- Return type:
- class varats.experiment.experiment_util.VersionExperiment(name=NOTHING, projects=NOTHING, id=NOTHING, schema=NOTHING, container=NOTHING)[source]
Bases:
ExperimentBase class for experiments that want to analyze different project revisions.
- REPORT_SPEC: ReportSpecification
- SHORTHAND: str
- classmethod shorthand()[source]
Experiment shorthand.
- Return type:
str
- classmethod report_spec()[source]
Experiment report specification.
- Return type:
- classmethod file_belongs_to_experiment(file_name)[source]
Checks if the file belongs to this experiment.
- Parameters:
file_name (
str) – name of the file to check- Return type:
bool- Returns:
True, if the file belongs to this experiment type
- get_handle()[source]
- Return type:
- abstractmethod actions_for_project(project)[source]
Get the actions a project wants to run.
- Return type:
MutableSequence[Step]
- classmethod sample(prj_cls)[source]
Adapt version sampling process if needed, otherwise fallback to default implementation.
- Parameters:
prj_cls (
Type[Project]) – project class- Return type:
List[Revision]- Returns:
list of sampled versions
- name: str
- projects: List[Type[Project]]
- container: ContainerImage
- class varats.experiment.experiment_util.ZippedReportFolder(result_report_path)[source]
Bases:
TemporaryDirectory[str]Context manager for creating a folder report, i.e., a report file which is actually a folder containing multiple files and other folders.
Example usage: An experiment step can, with this context manager, simply create a folder into which all kinds of data is dropped into. After the completion of the step (leaving the context manager), all files dropped into the folder will be compressed and stored as a single report.
- exception varats.experiment.experiment_util.WrongStepCall[source]
Bases:
ExceptionThrow if the common step method was called.
- class varats.experiment.experiment_util.OutputFolderStep(project)[source]
Bases:
ProjectStepSpecial step class that needs an output folder to write to.
- abstractmethod call_with_output_folder(tmp_dir)[source]
Actual call implementation that gets a path to tmp_folder.
- Return type:
StepResult
- class varats.experiment.experiment_util.ZippedExperimentSteps(output_filepath, actions)[source]
Bases:
MultiStep[ZippedStepTy]Runs multiple actions, providing them a shared tmp folder that afterwards is zipped into an archive.
- NAME: ClassVar[str] = 'ZippedSteps'
- DESCRIPTION: ClassVar[str] = 'Run multiple actions with a shared tmp folder'
- varats.experiment.experiment_util.create_new_success_result_filepath(exp_handle, report_type, project, binary, config_id=None)[source]
Create a result filepath for a successfull report of the executed experiment/project combination.
- Parameters:
exp_handle (
ExperimentHandle) – handle to the current experimentreport_type (
Type[BaseReport]) – type of the reportproject (
VProject) – current projectbinary (
ProjectBinaryWrapper) – current binaryconfig_id (
int|None) – optional id to specify the used configuration
- Return type:
Returns: formatted success filepath
- varats.experiment.experiment_util.create_new_failed_result_filepath(exp_handle, report_type, project, binary, config_id=None)[source]
Create a result filepath for a failed report of the executed experiment/project combination.
- Parameters:
exp_handle (
ExperimentHandle) – handle to the current experimentreport_type (
Type[BaseReport]) – type of the reportproject (
VProject) – current projectbinary (
ProjectBinaryWrapper) – current binaryconfig_id (
int|None) – optional id to specify the used configuration
- Return type:
Returns: formatted fail filepath
- varats.experiment.experiment_util.get_config_patch_steps(project)[source]
Get a list of actions that apply all configuration patches to the project.
- Parameters:
project (
VProject) – the project to be configured- Return type:
MutableSequence[Step]- Returns:
the actions that configure the project