import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
-import org.sonar.api.utils.log.Logger;
+import javax.annotation.Nullable;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.util.logs.Profiler;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Iterables.concat;
*/
public class VisitorsCrawler implements ComponentCrawler {
- private static final Logger LOGGER = Loggers.get(VisitorsCrawler.class);
-
+ private final Map<ComponentVisitor, VisitorDuration> visitorCumulativeDurations;
private final List<VisitorWrapper> preOrderVisitorWrappers;
private final List<VisitorWrapper> postOrderVisitorWrappers;
List<VisitorWrapper> visitorWrappers = from(visitors).transform(ToVisitorWrapper.INSTANCE).toList();
this.preOrderVisitorWrappers = from(visitorWrappers).filter(MathPreOrderVisitor.INSTANCE).toList();
this.postOrderVisitorWrappers = from(visitorWrappers).filter(MatchPostOrderVisitor.INSTANCE).toList();
+ this.visitorCumulativeDurations = from(visitors).toMap(VisitorWrapperToInitialDuration.INSTANCE);
+ }
+
+ public Map<ComponentVisitor, Long> getCumulativeDurations() {
+ return ImmutableMap.copyOf(
+ Maps.transformValues(this.visitorCumulativeDurations, VisitorDurationToDuration.INSTANCE)
+ );
}
@Override
}
private void visitNode(Component component, VisitorWrapper visitor) {
- LOGGER.trace("Visitor '{}' is currently visiting component {}", visitor, component);
+ Profiler profiler = Profiler.create(Loggers.get(visitor.getWrappedVisitor().getClass()))
+ .startTrace("Visiting component {}", component.getKey());
visitor.visitAny(component);
switch (component.getType()) {
case PROJECT:
default:
throw new IllegalStateException(String.format("Unknown type %s", component.getType().name()));
}
+ long duration = profiler.stopTrace();
+ incrementDuration(visitor, duration);
+ }
+
+ private void incrementDuration(VisitorWrapper visitorWrapper, long duration) {
+ visitorCumulativeDurations.get(visitorWrapper.getWrappedVisitor()).increment(duration);
}
private enum ToVisitorWrapper implements Function<ComponentVisitor, VisitorWrapper> {
return visitorWrapper.getOrder() == ComponentVisitor.Order.POST_ORDER;
}
}
+
+ private static final class VisitorDuration {
+ private long duration = 0;
+
+ public void increment(long duration) {
+ this.duration += duration;
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+ }
+
+ private enum VisitorWrapperToInitialDuration implements Function<ComponentVisitor, VisitorDuration> {
+ INSTANCE;
+
+ @Override
+ @Nonnull
+ public VisitorDuration apply(@Nonnull ComponentVisitor visitorWrapper) {
+ return new VisitorDuration();
+ }
+ }
+
+ private enum VisitorDurationToDuration implements Function<VisitorDuration, Long> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public Long apply(VisitorDuration input) {
+ return input.getDuration();
+ }
+ }
}
package org.sonar.server.computation.step;
import java.util.List;
+import java.util.Map;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.server.computation.component.ComponentVisitor;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.component.VisitorsCrawler;
public class ExecuteVisitorsStep implements ComputationStep {
+
+ private static final Logger LOGGER = Loggers.get(ExecuteVisitorsStep.class);
+
private final TreeRootHolder treeRootHolder;
private final List<ComponentVisitor> visitors;
}
@Override
- public void execute() {
- new VisitorsCrawler(visitors).visit(treeRootHolder.getRoot());
+ public String getDescription() {
+ return "Execute Component Visitors";
}
@Override
- public String getDescription() {
- return "Execute visitors";
+ public void execute() {
+ VisitorsCrawler visitorsCrawler = new VisitorsCrawler(visitors);
+ visitorsCrawler.visit(treeRootHolder.getRoot());
+ logVisitorExecutionDurations(visitors, visitorsCrawler);
+ }
+
+ private static void logVisitorExecutionDurations(List<ComponentVisitor> visitors, VisitorsCrawler visitorsCrawler) {
+ LOGGER.info(" Execution time for each Component visitor:");
+ Map<ComponentVisitor, Long> cumulativeDurations = visitorsCrawler.getCumulativeDurations();
+ for (ComponentVisitor visitor : visitors) {
+ LOGGER.info(" - {} | time={}ms", visitor.getClass().getSimpleName(), cumulativeDurations.get(visitor));
+ }
}
}