From 3556759b28bc03653d2318a838c159bf3bf2fdcc Mon Sep 17 00:00:00 2001 From: RamSaw Date: Mon, 20 Aug 2018 14:25:18 +0300 Subject: [PATCH 1/3] Added exclusion of HAC execution when project is large. Empty result isn't considered so it doesn't affect accuracy. Open questions: what bounds to put? And change AlgorithmResult to throw exception if algorithm execution ended with exception. --- .../research/groups/ml_methods/algorithm/HAC.java | 15 +++++++++++++++ .../algorithm/RefactoringExecutionContext.java | 4 +++- .../algorithm/TooLargeProjectException.java | 7 +++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/TooLargeProjectException.java diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java index ca969190..8de8609e 100755 --- a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java @@ -19,6 +19,7 @@ import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; @@ -26,6 +27,9 @@ public class HAC extends AbstractAlgorithm { private static final Logger LOGGER = Logging.getLogger(HAC.class); + private static final int MAX_NUMBER_OF_CLASSES = 3000; + private static final int MAX_NUMBER_OF_METHODS = 20000; + private static final int MAX_NUMBER_OF_FIELDS = 9000; private static final double ACCURACY = 1; private static final @NotNull DistanceCalculator distanceCalculator = RelevanceBasedDistanceCalculator.getInstance(); @@ -44,6 +48,17 @@ public HAC() { return new HACExecutor(); } + @NotNull + @Override + public AlgorithmResult execute(@NotNull AttributesStorage attributes, @Nullable ExecutorService service, boolean enableFieldRefactorings) { + if (attributes.getClassesAttributes().size() > MAX_NUMBER_OF_CLASSES || + attributes.getMethodsAttributes().size() > MAX_NUMBER_OF_METHODS || + attributes.getFieldsAttributes().size() > MAX_NUMBER_OF_FIELDS) { + return new AlgorithmResult(AlgorithmType.HAC, new TooLargeProjectException("HAC execution will be too long on this project")); + } + return super.execute(attributes, service, enableFieldRefactorings); + } + private static class HACExecutor implements Executor { private final SortedSet heap = new TreeSet<>(); private final Map triples = new HashMap<>(); diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/RefactoringExecutionContext.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/RefactoringExecutionContext.java index df04bc67..f9d92eab 100644 --- a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/RefactoringExecutionContext.java +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/RefactoringExecutionContext.java @@ -150,7 +150,9 @@ private void calculate(Algorithm algorithm) { final AlgorithmResult result = algorithm.execute(attributes, executorService, enableFieldRefactoring); - algorithmsResults.add(result); + if (result.isSuccess()) { + algorithmsResults.add(result); + } } public List getAlgorithmResults() { diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/TooLargeProjectException.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/TooLargeProjectException.java new file mode 100644 index 00000000..86f6f6b4 --- /dev/null +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/TooLargeProjectException.java @@ -0,0 +1,7 @@ +package org.jetbrains.research.groups.ml_methods.algorithm; + +class TooLargeProjectException extends Exception { + TooLargeProjectException(String message) { + super(message); + } +} From 2ac05d7fd1c3e9f7c5976e7876b031200d36e9d7 Mon Sep 17 00:00:00 2001 From: RamSaw Date: Mon, 20 Aug 2018 14:43:36 +0300 Subject: [PATCH 2/3] Changed AlgorithmResult. Now if algorithm ended with exception and isSuccess returns false then calling of getRefactorings(), getExecutionTime() or getThreadUsed() will throw a RuntimeException. --- .../algorithm/AlgorithmFailedException.java | 7 ++++++ .../ml_methods/algorithm/AlgorithmResult.java | 25 +++++++++++++------ .../groups/ml_methods/algorithm/HAC.java | 4 ++- 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmFailedException.java diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmFailedException.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmFailedException.java new file mode 100644 index 00000000..9c1bce30 --- /dev/null +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmFailedException.java @@ -0,0 +1,7 @@ +package org.jetbrains.research.groups.ml_methods.algorithm; + +class AlgorithmFailedException extends RuntimeException { + AlgorithmFailedException(String message) { + super(message); + } +} diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmResult.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmResult.java index 1d8785df..3aae08ef 100644 --- a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmResult.java +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/AlgorithmResult.java @@ -7,6 +7,7 @@ import java.util.Collections; import java.util.List; +import java.util.Objects; public class AlgorithmResult { private final List refactorings; @@ -25,7 +26,7 @@ public class AlgorithmResult { } AlgorithmResult(AlgorithmType algorithmType, @NotNull Exception exception) { - this.refactorings = Collections.emptyList(); + this.refactorings = null; this.algorithmType = algorithmType; this.executionTime = 0; this.threadUsed = 0; @@ -33,7 +34,8 @@ public class AlgorithmResult { } public List getRefactorings() { - return Collections.unmodifiableList(refactorings); + throwIfNotSuccess(); + return Collections.unmodifiableList(Objects.requireNonNull(refactorings)); } public AlgorithmType getAlgorithmType() { @@ -41,10 +43,12 @@ public AlgorithmType getAlgorithmType() { } public long getExecutionTime() { + throwIfNotSuccess(); return executionTime; } public int getThreadUsed() { + throwIfNotSuccess(); return threadUsed; } @@ -53,14 +57,21 @@ public Exception getException() { return exception; } - public boolean isSuccess() { + boolean isSuccess() { return exception == null; } - public String getReport() { - return "Results of " + algorithmType + " running" + System.lineSeparator() + - " Found " + refactorings.size() + " refactorings" + System.lineSeparator() + + private void throwIfNotSuccess() { + if (!isSuccess()) { + throw new AlgorithmFailedException("Algorithm ended with exception. Requested data cannot be retrieved."); + } + } + + String getReport() { + return isSuccess() ? "Results of " + algorithmType + " running" + System.lineSeparator() + + " Found " + Objects.requireNonNull(refactorings).size() + " refactorings" + System.lineSeparator() + " Execution time: " + executionTime + System.lineSeparator() + - " Threads used: " + threadUsed; + " Threads used: " + threadUsed : + algorithmType + " failed with exception: " + Objects.requireNonNull(exception).getMessage(); } } diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java index 8de8609e..bca49d25 100755 --- a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java @@ -54,7 +54,9 @@ public AlgorithmResult execute(@NotNull AttributesStorage attributes, @Nullable if (attributes.getClassesAttributes().size() > MAX_NUMBER_OF_CLASSES || attributes.getMethodsAttributes().size() > MAX_NUMBER_OF_METHODS || attributes.getFieldsAttributes().size() > MAX_NUMBER_OF_FIELDS) { - return new AlgorithmResult(AlgorithmType.HAC, new TooLargeProjectException("HAC execution will be too long on this project")); + LOGGER.warn("HAC haven't been executed because project is too large and HAC will work too long"); + return new AlgorithmResult(AlgorithmType.HAC, + new TooLargeProjectException("HAC execution will be too long on this project")); } return super.execute(attributes, service, enableFieldRefactorings); } From 98872b633cf633a82e4c228ab60e67cdb6d8f70e Mon Sep 17 00:00:00 2001 From: RamSaw Date: Mon, 20 Aug 2018 15:11:13 +0300 Subject: [PATCH 3/3] Corrected bounds. --- .../groups/ml_methods/algorithm/HAC.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java index bca49d25..0e0ca6e4 100755 --- a/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java +++ b/core/src/main/java/org/jetbrains/research/groups/ml_methods/algorithm/HAC.java @@ -27,9 +27,9 @@ public class HAC extends AbstractAlgorithm { private static final Logger LOGGER = Logging.getLogger(HAC.class); - private static final int MAX_NUMBER_OF_CLASSES = 3000; - private static final int MAX_NUMBER_OF_METHODS = 20000; - private static final int MAX_NUMBER_OF_FIELDS = 9000; + private static final int MAX_NUMBER_OF_CLASSES = 1000; + private static final int MAX_NUMBER_OF_METHODS = 3000; + private static final int MAX_NUMBER_OF_FIELDS = 1500; private static final double ACCURACY = 1; private static final @NotNull DistanceCalculator distanceCalculator = RelevanceBasedDistanceCalculator.getInstance(); @@ -51,9 +51,7 @@ public HAC() { @NotNull @Override public AlgorithmResult execute(@NotNull AttributesStorage attributes, @Nullable ExecutorService service, boolean enableFieldRefactorings) { - if (attributes.getClassesAttributes().size() > MAX_NUMBER_OF_CLASSES || - attributes.getMethodsAttributes().size() > MAX_NUMBER_OF_METHODS || - attributes.getFieldsAttributes().size() > MAX_NUMBER_OF_FIELDS) { + if (willHaveLongTimeExecution(attributes)) { LOGGER.warn("HAC haven't been executed because project is too large and HAC will work too long"); return new AlgorithmResult(AlgorithmType.HAC, new TooLargeProjectException("HAC execution will be too long on this project")); @@ -61,6 +59,12 @@ public AlgorithmResult execute(@NotNull AttributesStorage attributes, @Nullable return super.execute(attributes, service, enableFieldRefactorings); } + private boolean willHaveLongTimeExecution(@NotNull AttributesStorage attributes) { + return attributes.getClassesAttributes().size() > MAX_NUMBER_OF_CLASSES || + attributes.getMethodsAttributes().size() > MAX_NUMBER_OF_METHODS || + attributes.getFieldsAttributes().size() > MAX_NUMBER_OF_FIELDS; + } + private static class HACExecutor implements Executor { private final SortedSet heap = new TreeSet<>(); private final Map triples = new HashMap<>();