From: Alexandre Montplaisir Date: Thu, 30 Jun 2016 20:55:31 +0000 (-0400) Subject: tmf: Cache CallStackEvent names X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=6f8332c4beb8b962b8561b117cd3fb722cc3e507;p=deliverable%2Ftracecompass.git tmf: Cache CallStackEvent names This will avoid calling the symbol provider repeatedly, which equates to a state system query + calling an external process for LTTng-UST traces, for examples. Change-Id: I798c0d253b2ba83529c98b99b70481430ea1a613 Signed-off-by: Alexandre Montplaisir Reviewed-on: https://git.eclipse.org/r/76400 Reviewed-by: Hudson CI --- diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF index e3ffcebb4c..77609d5973 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF +++ b/tmf/org.eclipse.tracecompass.tmf.ui/META-INF/MANIFEST.MF @@ -108,6 +108,7 @@ Export-Package: org.eclipse.tracecompass.internal.tmf.ui;x-friends:="org.eclipse org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets, org.eclipse.tracecompass.tmf.ui.widgets.virtualtable Import-Package: com.google.common.base, + com.google.common.cache, com.google.common.collect, org.eclipse.emf.common.util, org.eclipse.emf.ecore diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackEvent.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackEvent.java index e56959052e..c2782e29e1 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackEvent.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackEvent.java @@ -36,4 +36,14 @@ public class CallStackEvent extends TimeEvent { public CallStackEvent(CallStackEntry entry, long time, long duration, int value) { super(entry, time, duration, value); } + + /** + * @since 2.1 + */ + @Override + public CallStackEntry getEntry() { + /* Type enforced at constructor */ + return (CallStackEntry) fEntry; + } + } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java index 2631bc72f0..b6478f028a 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackPresentationProvider.java @@ -12,6 +12,8 @@ package org.eclipse.tracecompass.tmf.ui.views.callstack; +import java.util.Optional; + import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.RGB; @@ -29,6 +31,10 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + /** * Presentation provider for the Call Stack view, based on the generic TMF * presentation provider. @@ -44,6 +50,28 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider private Integer fAverageCharWidth; + private final LoadingCache> fTimeEventNames = CacheBuilder.newBuilder() + .maximumSize(1000) + .build(new CacheLoader>() { + @Override + public Optional load(CallStackEvent event) { + CallStackEntry entry = event.getEntry(); + ITmfStateSystem ss = entry.getStateSystem(); + try { + ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue(); + if (!value.isNull()) { + String name = fView.getFunctionName(entry.getTrace(), entry.getProcessId(), event.getTime(), value); + return Optional.ofNullable(name); + } + } catch (TimeRangeException e) { + Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$ + } catch (StateSystemDisposedException e) { + /* Ignored */ + } + return Optional.empty(); + } + }); + private enum State { MULTIPLE (new RGB(100, 100, 100)), EXEC (new RGB(0, 200, 0)); @@ -106,19 +134,7 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider @Override public String getEventName(ITimeEvent event) { if (event instanceof CallStackEvent) { - CallStackEntry entry = (CallStackEntry) event.getEntry(); - ITmfStateSystem ss = entry.getStateSystem(); - try { - ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue(); - if (!value.isNull()) { - return fView.getFunctionName(entry.getTrace(), entry.getProcessId(), event.getTime(), value); - } - } catch (TimeRangeException e) { - Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$ - } catch (StateSystemDisposedException e) { - /* Ignored */ - } - return null; + return fTimeEventNames.getUnchecked((CallStackEvent) event).orElse(null); } return State.MULTIPLE.toString(); } @@ -134,20 +150,17 @@ public class CallStackPresentationProvider extends TimeGraphPresentationProvider if (!(event instanceof CallStackEvent)) { return; } - CallStackEntry entry = (CallStackEntry) event.getEntry(); - ITmfStateSystem ss = entry.getStateSystem(); - try { - ITmfStateValue value = ss.querySingleState(event.getTime(), entry.getQuark()).getStateValue(); - if (!value.isNull()) { - String name = fView.getFunctionName(entry.getTrace(), entry.getProcessId(), event.getTime(), value); - gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE)); - Utils.drawText(gc, name, bounds.x, bounds.y, bounds.width, bounds.height, true, true); - } - } catch (TimeRangeException e) { - Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$ - } catch (StateSystemDisposedException e) { - /* Ignored */ - } + String name = fTimeEventNames.getUnchecked((CallStackEvent) event).orElse(null); + gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE)); + Utils.drawText(gc, name, bounds.x, bounds.y, bounds.width, bounds.height, true, true); + } + + /** + * Indicate that the provider of function names has changed, so any cached + * values must be reset. + */ + void resetFunctionNames() { + fTimeEventNames.invalidateAll(); } } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackView.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackView.java index 5f4524cc17..749bc3ce67 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackView.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackView.java @@ -361,7 +361,7 @@ public class CallStackView extends AbstractTimeGraphView { */ public CallStackView() { super(ID, new CallStackPresentationProvider()); - ((CallStackPresentationProvider) getPresentationProvider()).setCallStackView(this); + getPresentationProvider().setCallStackView(this); setTreeColumns(COLUMN_NAMES); setTreeLabelProvider(new CallStackTreeLabelProvider()); setEntryComparator(new CallStackComparator()); @@ -501,6 +501,15 @@ public class CallStackView extends AbstractTimeGraphView { // Internal // ------------------------------------------------------------------------ + /** + * @since 2.1 + */ + @Override + protected CallStackPresentationProvider getPresentationProvider() { + /* Set to this type by the constructor */ + return (CallStackPresentationProvider) super.getPresentationProvider(); + } + @Override @TmfSignalHandler public void traceClosed(TmfTraceClosedSignal signal) { @@ -1220,6 +1229,7 @@ public class CallStackView extends AbstractTimeGraphView { public void run() { SymbolProviderConfigDialog dialog = new SymbolProviderConfigDialog(getSite().getShell(), getProviderPages()); if (dialog.open() == IDialogConstants.OK_ID) { + getPresentationProvider().resetFunctionNames(); refresh(); } } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/model/TimeEvent.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/model/TimeEvent.java index 189b8bafc3..c66ea4d8f1 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/model/TimeEvent.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/model/TimeEvent.java @@ -13,6 +13,8 @@ package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model; +import java.util.Objects; + /** * Generic TimeEvent implementation * @@ -120,6 +122,29 @@ public class TimeEvent implements ITimeEvent { null); } + @Override + public int hashCode() { + return Objects.hash(fEntry, fTime, fDuration, fValue); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TimeEvent other = (TimeEvent) obj; + return Objects.equals(fEntry, other.fEntry) && + Objects.equals(fTime, other.fTime) && + Objects.equals(fDuration, other.fDuration) && + Objects.equals(fValue, other.fValue); + } + @Override public String toString() { return getClass().getSimpleName() + " start=" + fTime + " end=" + (fTime + fDuration) + " duration=" + fDuration + (hasValue() ? (" value=" + fValue) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$