diff --git a/src/main/injectors/GenericMergeModule.groovy b/src/main/injectors/GenericMergeModule.groovy index 5ddbf7382..9ce457a4a 100644 --- a/src/main/injectors/GenericMergeModule.groovy +++ b/src/main/injectors/GenericMergeModule.groovy @@ -14,6 +14,7 @@ import services.dataCollectors.GenericMerge.GenericMergeDataCollector import services.dataCollectors.GenericMerge.MergeConflictsComparator import services.dataCollectors.GenericMerge.MergeToolsComparator import services.dataCollectors.GenericMerge.ScenarioLOCsCounter +import services.dataCollectors.GenericMerge.UnstructuredMergeCollector import services.outputProcessors.GenericMergeDataOutputProcessor import services.projectProcessors.DummyProjectProcessor import services.util.ci.CIPlatform @@ -35,6 +36,7 @@ class GenericMergeModule extends AbstractModule { dataCollectorBinder.addBinding().to(GenericMergeDataCollector.class) dataCollectorBinder.addBinding().to(MergeToolsComparator.class) dataCollectorBinder.addBinding().to(MergeConflictsComparator.class) + dataCollectorBinder.addBinding().to(UnstructuredMergeCollector.class) Multibinder outputProcessorBinder = Multibinder.newSetBinder(binder(), OutputProcessor.class) outputProcessorBinder.addBinding().to(GenericMergeDataOutputProcessor.class) diff --git a/src/main/services/dataCollectors/GenericMerge/GenericMergeConfig.groovy b/src/main/services/dataCollectors/GenericMerge/GenericMergeConfig.groovy index 1db1561f0..c503ab2ba 100644 --- a/src/main/services/dataCollectors/GenericMerge/GenericMergeConfig.groovy +++ b/src/main/services/dataCollectors/GenericMerge/GenericMergeConfig.groovy @@ -11,6 +11,7 @@ class GenericMergeConfig { public static final GENERIC_MERGE_REPORT_MERGE_CONFLICTS = "${GENERIC_MERGE_REPORT_PATH}/generic-merge-merge-conflicts.csv" public static final GENERIC_MERGE_REPORT_COMMITS_FILE_NAME = "${GENERIC_MERGE_REPORT_PATH}/generic-merge-execution-commits.csv" public static final GENERIC_MERGE_REPORT_SCENARIO_LOCS_FILE_NAME = "${GENERIC_MERGE_REPORT_PATH}/generic-merge-scenario-locs.csv" + public static final GENERIC_MERGE_REPORT_UNSTRUCTURED_TIMES_FILE_NAME = "${GENERIC_MERGE_REPORT_PATH}/generic-merge-unstructured-times.csv" public static final String GENERIC_MERGE_BINARY_PATH = "${BASE_EXPERIMENT_PATH}/tools/generic-merge" public static final String JDIME_BINARY_PATH = "${BASE_EXPERIMENT_PATH}/tools/jdime/install/JDime/bin" diff --git a/src/main/services/dataCollectors/GenericMerge/UnstructuredMergeCollector.groovy b/src/main/services/dataCollectors/GenericMerge/UnstructuredMergeCollector.groovy new file mode 100644 index 000000000..9568b7432 --- /dev/null +++ b/src/main/services/dataCollectors/GenericMerge/UnstructuredMergeCollector.groovy @@ -0,0 +1,52 @@ +package services.dataCollectors.GenericMerge + +import interfaces.DataCollector +import project.MergeCommit +import project.Project +import services.dataCollectors.S3MMergesCollector.MergeScenarioCollector +import services.mergeScenariosFilters.NonFastForwardMergeScenarioFilter +import util.CsvUtils +import util.ProcessRunner + +import java.nio.file.Path + +class UnstructuredMergeCollector implements DataCollector { + @Override + void collectData(Project project, MergeCommit mergeCommit) { + def scenarios = MergeScenarioCollector.collectMergeScenarios(project, mergeCommit) + .stream() + .filter(NonFastForwardMergeScenarioFilter::isNonFastForwardMergeScenario) + .map(scenario -> { + def executionTime = runGitMergeFile(scenario) + return [project.getName(), mergeCommit.getSHA(), scenario.toString(), executionTime] + }) + .map(CsvUtils::toCsvRepresentation) + + def reportFile = new File(GenericMergeConfig.GENERIC_MERGE_REPORT_UNSTRUCTURED_TIMES_FILE_NAME) + reportFile << scenarios.collect(CsvUtils.asLines()) << "\n" + } + + private static long runGitMergeFile(Path scenario) { + def executionTimes = new ArrayList() + + for (int i = 0; i < GenericMergeConfig.NUMBER_OF_EXECUTIONS; i++) { + long startTime = System.nanoTime() + + def processBuilder = ProcessRunner.buildProcess(GenericMergeConfig.BASE_EXPERIMENT_PATH, + "git", + "merge-file", + scenario.resolve("left.java").toString(), + scenario.resolve("base.java").toString(), + scenario.resolve("right.java").toString()) + ProcessRunner.startProcess(processBuilder).waitFor() + + long endTime = System.nanoTime() + // If we're running more than one execution, we use the first one as a warm up + if (GenericMergeConfig.NUMBER_OF_EXECUTIONS == 1 || i > 0) { + executionTimes.add(endTime - startTime) + } + } + + return (long) (executionTimes.stream().reduce(0, (prev, cur) -> prev + cur) / executionTimes.size()) + } +}