diff --git a/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatchRule.java b/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatchRule.java index 71ef422ba..b4623c717 100644 --- a/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatchRule.java +++ b/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatchRule.java @@ -14,8 +14,8 @@ import java.io.PrintStream; import java.util.Map; import java.util.Map.Entry; -import org.eclipse.xtext.util.internal.StopWatches; -import org.eclipse.xtext.util.internal.StopWatches.NumbersForTask; +import org.eclipse.xtext.util.internal.Stopwatches; +import org.eclipse.xtext.util.internal.Stopwatches.NumbersForTask; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; @@ -23,23 +23,22 @@ import org.junit.runners.model.Statement; /** * @author Sven Efftinge - Initial contribution and API */ -public class StopWatchRule implements TestRule { +public class StopwatchRule implements TestRule { private boolean watchAll = false; - public StopWatchRule() { + public StopwatchRule() { } /** - * @param watchAll - * - whether all tests should be watched (true) or just the ones annotated with @ - * {@link StopWatched} (false). + * @param watchAll true if all tests should be timed, false + * if only tests should be considered which are annotated with {@link Timed @Timed} */ - public StopWatchRule(boolean watchAll) { + public StopwatchRule(boolean watchAll) { this.watchAll = watchAll; } - public void printStopWatchData(Description description, Map data) { + public void printStopwatchData(Description description, Map data) { String property = System.getProperty("stopwatch.file"); PrintStream out = System.out; FileOutputStream outputStream = null; @@ -54,7 +53,7 @@ public class StopWatchRule implements TestRule { try { out.println("-------------------------------------------------------------------------------------------------------------------------\n"); out.println("Test '" + description.getDisplayName() + "' :"); - out.println(getStopWatchDataAsReadableString(data)); + out.println(getStopwatchDataAsReadableString(data)); } finally { // out.flush(); if (outputStream != null) @@ -66,7 +65,7 @@ public class StopWatchRule implements TestRule { } } - public String getStopWatchDataAsReadableString(Map data) { + public String getStopwatchDataAsReadableString(Map data) { StringBuilder sb = new StringBuilder(); sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); for (Entry task : data.entrySet()) { @@ -78,19 +77,19 @@ public class StopWatchRule implements TestRule { } public Statement apply(final Statement base, final Description description) { - if (!watchAll && description.getAnnotation(StopWatched.class) == null) + if (!watchAll && description.getAnnotation(Timed.class) == null) return base; return new Statement() { @Override public void evaluate() throws Throwable { try { - StopWatches.setEnabled(true); - StopWatches.resetAll(); + Stopwatches.setEnabled(true); + Stopwatches.resetAll(); base.evaluate(); } finally { - printStopWatchData(description, StopWatches.allNumbers()); - StopWatches.resetAll(); - StopWatches.setEnabled(false); + printStopwatchData(description, Stopwatches.allNumbers()); + Stopwatches.resetAll(); + Stopwatches.setEnabled(false); } } }; diff --git a/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopwatchRule.java b/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopwatchRule.java new file mode 100644 index 000000000..b4623c717 --- /dev/null +++ b/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopwatchRule.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.junit4.internal; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.xtext.util.internal.Stopwatches; +import org.eclipse.xtext.util.internal.Stopwatches.NumbersForTask; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Sven Efftinge - Initial contribution and API + */ +public class StopwatchRule implements TestRule { + + private boolean watchAll = false; + + public StopwatchRule() { + } + + /** + * @param watchAll true if all tests should be timed, false + * if only tests should be considered which are annotated with {@link Timed @Timed} + */ + public StopwatchRule(boolean watchAll) { + this.watchAll = watchAll; + } + + public void printStopwatchData(Description description, Map data) { + String property = System.getProperty("stopwatch.file"); + PrintStream out = System.out; + FileOutputStream outputStream = null; + if (property != null) { + try { + outputStream = new FileOutputStream(new File(property), true); + out = new PrintStream(outputStream); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + out.println("-------------------------------------------------------------------------------------------------------------------------\n"); + out.println("Test '" + description.getDisplayName() + "' :"); + out.println(getStopwatchDataAsReadableString(data)); + } finally { +// out.flush(); + if (outputStream != null) + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public String getStopwatchDataAsReadableString(Map data) { + StringBuilder sb = new StringBuilder(); + sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); + for (Entry task : data.entrySet()) { + sb.append("Task '" + task.getKey() + "' took " + task.getValue().getMilliseconds() + "ms (" + + task.getValue().getNumberOfMeasurements() + " measurements).\n"); + } + sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); + return sb.toString(); + } + + public Statement apply(final Statement base, final Description description) { + if (!watchAll && description.getAnnotation(Timed.class) == null) + return base; + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + Stopwatches.setEnabled(true); + Stopwatches.resetAll(); + base.evaluate(); + } finally { + printStopwatchData(description, Stopwatches.allNumbers()); + Stopwatches.resetAll(); + Stopwatches.setEnabled(false); + } + } + }; + } + +} diff --git a/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatched.java b/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/Timed.java similarity index 91% rename from plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatched.java rename to plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/Timed.java index 976e86021..f990b9c38 100644 --- a/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/StopWatched.java +++ b/plugins/org.eclipse.xtext.junit4/src/org/eclipse/xtext/junit4/internal/Timed.java @@ -7,6 +7,7 @@ *******************************************************************************/ package org.eclipse.xtext.junit4.internal; +import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -17,6 +18,7 @@ import java.lang.annotation.Target; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) -public @interface StopWatched { +@Documented +public @interface Timed { } diff --git a/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/StopWatches.java b/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/StopWatches.java index e87444891..d78c2114b 100644 --- a/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/StopWatches.java +++ b/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/StopWatches.java @@ -16,21 +16,21 @@ import java.util.Map.Entry; /** * @author Sven Efftinge - Initial contribution and API */ -public class StopWatches { +public class Stopwatches { public interface StoppedTask { public void start(); public void stop(); } - public static class StopWatchForTask implements StoppedTask { + public static class StopwatchForTask implements StoppedTask { final static long notRunning = -1; private NumbersForTask numbers; private long lastStart = notRunning; private int reentrant = 0; - StopWatchForTask(NumbersForTask numbers) { + StopwatchForTask(NumbersForTask numbers) { this.numbers = numbers; } @@ -94,7 +94,7 @@ public class StopWatches { numbers = new NumbersForTask(); data.put(task, numbers); } - return new StopWatchForTask(numbers); + return new StopwatchForTask(numbers); } } @@ -114,11 +114,11 @@ public class StopWatches { } } - public static String getPrintableStopWatchData() { + public static String getPrintableStopwatchData() { StringBuilder sb = new StringBuilder(); sb.append("\n"); sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); - for (Entry task : StopWatches.allNumbers().entrySet()) { + for (Entry task : Stopwatches.allNumbers().entrySet()) { sb.append("Task '"+task.getKey()+"' took "+task.getValue().getMilliseconds()+"ms ("+task.getValue().getNumberOfMeasurements()+" measurements).\n"); } sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); diff --git a/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/Stopwatches.java b/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/Stopwatches.java new file mode 100644 index 000000000..d78c2114b --- /dev/null +++ b/plugins/org.eclipse.xtext.util/src/org/eclipse/xtext/util/internal/Stopwatches.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.util.internal; + +import static com.google.common.collect.Maps.*; +import static java.util.Collections.*; + +import java.util.Map; +import java.util.Map.Entry; + +/** + * @author Sven Efftinge - Initial contribution and API + */ +public class Stopwatches { + + public interface StoppedTask { + public void start(); + public void stop(); + } + + public static class StopwatchForTask implements StoppedTask { + final static long notRunning = -1; + + private NumbersForTask numbers; + private long lastStart = notRunning; + private int reentrant = 0; + + StopwatchForTask(NumbersForTask numbers) { + this.numbers = numbers; + } + + public void start() { + if (!isRunning()) + lastStart = System.currentTimeMillis(); + reentrant++; + } + + public boolean isRunning() { + return lastStart != notRunning; + } + + public void stop() { + if (isRunning()) { + reentrant--; + if (reentrant == 0) { + long currentTimeMillis = System.currentTimeMillis(); + numbers.addMilliseconds(currentTimeMillis - lastStart); + numbers.increaseMeasurements(); + lastStart = notRunning; + } + } + } + } + + public static class NumbersForTask { + long milliseconds = 0; + int numberOfMeasurements = 0; + + public long getMilliseconds() { + return milliseconds; + } + + synchronized void addMilliseconds(long milliseconds) { + this.milliseconds += milliseconds; + } + + public int getNumberOfMeasurements() { + return numberOfMeasurements; + } + + synchronized void increaseMeasurements() { + this.numberOfMeasurements++; + } + } + + private static Map data = newLinkedHashMap(); + private static boolean enabled = false; + private static StoppedTask NULLIMPL = new StoppedTask() { + public void start() {} + public void stop() {} + }; + + public static StoppedTask forTask(String task) { + if (!enabled) + return NULLIMPL; + synchronized (data) { + NumbersForTask numbers = data.get(task); + if (numbers == null) { + numbers = new NumbersForTask(); + data.put(task, numbers); + } + return new StopwatchForTask(numbers); + } + } + + public static void setEnabled(boolean isEnabled) { + enabled = isEnabled; + } + + public static void resetAll() { + synchronized (data) { + data.clear(); + } + } + + public static Map allNumbers() { + synchronized (data) { + return unmodifiableMap(data); + } + } + + public static String getPrintableStopwatchData() { + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); + for (Entry task : Stopwatches.allNumbers().entrySet()) { + sb.append("Task '"+task.getKey()+"' took "+task.getValue().getMilliseconds()+"ms ("+task.getValue().getNumberOfMeasurements()+" measurements).\n"); + } + sb.append("-------------------------------------------------------------------------------------------------------------------------\n"); + return sb.toString(); + } + +} diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/DefaultLinkingService.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/DefaultLinkingService.java index ae7eb98e7..0835a3f6c 100755 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/DefaultLinkingService.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/linking/impl/DefaultLinkingService.java @@ -23,8 +23,8 @@ import org.eclipse.xtext.scoping.IScope; import org.eclipse.xtext.scoping.IScopeProvider; import org.eclipse.xtext.scoping.impl.AbstractGlobalScopeDelegatingScopeProvider; import org.eclipse.xtext.scoping.impl.IDelegatingScopeProvider; -import org.eclipse.xtext.util.internal.StopWatches; -import org.eclipse.xtext.util.internal.StopWatches.StoppedTask; +import org.eclipse.xtext.util.internal.Stopwatches; +import org.eclipse.xtext.util.internal.Stopwatches.StoppedTask; import com.google.inject.Inject; import com.google.inject.Provider; @@ -117,7 +117,7 @@ public class DefaultLinkingService extends AbstractLinkingService { if (logger.isDebugEnabled()) { logger.debug("before getLinkedObjects: node: '" + crossRefString + "'"); } - StoppedTask task = StopWatches.forTask("Crosslink resolution"); + StoppedTask task = Stopwatches.forTask("Crosslink resolution (DefaultLinkingService.getLinkedObjects)"); try { task.start(); final IScope scope = getScope(context, ref); diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parser/AbstractParser.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parser/AbstractParser.java index 6a20c0160..c1ee7633c 100755 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parser/AbstractParser.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/parser/AbstractParser.java @@ -11,8 +11,8 @@ package org.eclipse.xtext.parser; import java.io.Reader; import org.eclipse.xtext.util.ReplaceRegion; -import org.eclipse.xtext.util.internal.StopWatches; -import org.eclipse.xtext.util.internal.StopWatches.StoppedTask; +import org.eclipse.xtext.util.internal.Stopwatches; +import org.eclipse.xtext.util.internal.Stopwatches.StoppedTask; /** * @author Sven Efftinge - Initial contribution and API @@ -26,7 +26,7 @@ public abstract class AbstractParser implements IParser { } public final IParseResult parse(Reader reader) { - StoppedTask task = StopWatches.forTask("parsing"); + StoppedTask task = Stopwatches.forTask("AbstractParser.parse"); try { task.start(); return doParse(reader); diff --git a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/validation/ResourceValidatorImpl.java b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/validation/ResourceValidatorImpl.java index 9680c289f..3882660df 100755 --- a/plugins/org.eclipse.xtext/src/org/eclipse/xtext/validation/ResourceValidatorImpl.java +++ b/plugins/org.eclipse.xtext/src/org/eclipse/xtext/validation/ResourceValidatorImpl.java @@ -22,8 +22,8 @@ import org.eclipse.xtext.diagnostics.Severity; import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.util.CancelIndicator; import org.eclipse.xtext.util.IAcceptor; -import org.eclipse.xtext.util.internal.StopWatches; -import org.eclipse.xtext.util.internal.StopWatches.StoppedTask; +import org.eclipse.xtext.util.internal.Stopwatches; +import org.eclipse.xtext.util.internal.Stopwatches.StoppedTask; import org.eclipse.xtext.validation.impl.ConcreteSyntaxEValidator; import com.google.common.collect.Lists; @@ -60,7 +60,7 @@ public class ResourceValidatorImpl implements IResourceValidator { private IDiagnosticConverter converter; public List validate(Resource resource, final CheckMode mode, CancelIndicator mon) { - StoppedTask task = StopWatches.forTask("validation"); + StoppedTask task = Stopwatches.forTask("ResourceValidatorImpl.validation"); try { task.start(); final CancelIndicator monitor = mon == null ? CancelIndicator.NullImpl : mon;