tmf: make CallstackProvider entry and exit return TmfStates
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Fri, 15 Apr 2016 01:59:44 +0000 (21:59 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Thu, 5 May 2016 00:53:59 +0000 (20:53 -0400)
This allows certain callstacks to return simpler long or int
states instead of a string. Expect SIGNIFICANT space savings.

In an example application, ls was traced (coreutils 8
with -finstrument-functions)

For a 149 mb trace with no lost events.

State system size
before:
233 mb
after:
25mb

Total time for trace compass fullscreen (1920x1080)

read the trace and build the state systems:
before:
61.5 sec
after:
44.0 sec

average seek time (100ms window, 10 random locations)
before:
1.2 sec
after:
0.6 s

Change-Id: Ic868829296d92d854cda7b78784b6ee3be4d5a51
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/70719
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-by: Hudson CI
lttng/org.eclipse.tracecompass.lttng2.ust.core.tests/src/org/eclipse/tracecompass/lttng2/ust/core/tests/callstack/AbstractProviderTest.java
lttng/org.eclipse.tracecompass.lttng2.ust.core/src/org/eclipse/tracecompass/internal/lttng2/ust/core/callstack/LttngUstCallStackProvider.java
lttng/org.eclipse.tracecompass.lttng2.ust.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/ust/ui/swtbot/tests/CallStackViewTest.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/callstack/CallStackStateProvider.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/callstack/CallStackView.java

index e4bec226c91f44388280145ec12608dd29d1f98f..05e379a940205e5caf34ab7dfb549b3497f7cc22 100644 (file)
@@ -278,7 +278,7 @@ public abstract class AbstractProviderTest {
             String[] ret = new String[depth];
             for (int i = 0; i < depth; i++) {
                 int quark = ss.getQuarkRelative(stackAttribute, String.valueOf(i + 1));
-                ret[i] = state.get(quark).getStateValue().unboxStr();
+                ret[i] = Long.toHexString(state.get(quark).getStateValue().unboxLong());
             }
             return ret;
 
index 2729e6e0a47436c7b5b90ff30c95629a024ded97..1ff8606ce69d5e4197e33d37d33b3079c008342f 100644 (file)
@@ -21,6 +21,8 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.internal.lttng2.ust.core.trace.layout.LttngUst20EventLayout;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
 import org.eclipse.tracecompass.tmf.core.callstack.CallStackStateProvider;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
 import org.eclipse.tracecompass.tmf.core.event.ITmfEventField;
@@ -127,17 +129,17 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
     }
 
     @Override
-    public @Nullable String functionEntry(ITmfEvent event) {
+    public @Nullable ITmfStateValue functionEntry(ITmfEvent event) {
         String eventName = event.getName();
         if (!funcEntryEvents.contains(eventName)) {
             return null;
         }
         Long address = (Long) event.getContent().getField(fLayout.fieldAddr()).getValue();
-        return Long.toHexString(address);
+        return TmfStateValue.newValueLong(address);
     }
 
     @Override
-    public @Nullable String functionExit(ITmfEvent event) {
+    public @Nullable ITmfStateValue functionExit(ITmfEvent event) {
         String eventName = event.getName();
         if (!funcExitEvents.contains(eventName)) {
             return null;
@@ -148,10 +150,10 @@ public class LttngUstCallStackProvider extends CallStackStateProvider {
          */
         ITmfEventField field = event.getContent().getField(fLayout.fieldAddr());
         if (field == null) {
-            return CallStackStateProvider.UNDEFINED;
+            return TmfStateValue.nullValue();
         }
         Long address = (Long) field.getValue();
-        return Long.toHexString(address);
+        return TmfStateValue.newValueLong(address);
     }
 
     @Override
index 4524729641bf1ee5c205734a4642e482adb924eb..1f4d225293d84d2687ee18bc64fcf085eab6d4ed 100644 (file)
@@ -86,17 +86,17 @@ public class CallStackViewTest {
      * Stack frames of consecutive events in the trace
      */
     private static final String[] STACK_FRAMES[] = new String[][] {
-        {"40472b", "4045c8", "404412", "", ""},
-        {"40472b", "4045c8", "404412", "40392b", ""},
-        {"40472b", "4045c8", "404412", "", ""},
-        {"40472b", "4045c8", "", "", ""},
-        {"40472b", "4045c8", "404412", "", ""},
-        {"40472b", "4045c8", "404412", "40392b", ""},
-        {"40472b", "4045c8", "404412", "", ""},
-        {"40472b", "4045c8", "", "", ""},
-        {"40472b", "4045c8", "404412", "", ""},
-        {"40472b", "4045c8", "404412", "40392b", ""},
-        {"40472b", "4045c8", "404412", "", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "0x40392b", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "", ""},
+        {"0x40472b", "0x4045c8", "", "", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "0x40392b", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "", ""},
+        {"0x40472b", "0x4045c8", "", "", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "0x40392b", ""},
+        {"0x40472b", "0x4045c8", "0x404412", "", ""},
     };
 
     /** Tooltips of the toolbar buttons */
@@ -191,7 +191,7 @@ public class CallStackViewTest {
         String node = "glxgears-cyg-profile";
         String pid = "-1";
         String childName = "glxgears-16073";
-        List<String> expected = ImmutableList.of("40472b", "", "", "", "");
+        List<String> expected = ImmutableList.of("0x40472b", "", "", "", "");
 
         SWTBotView viewBot = fBot.viewById(CallStackView.ID);
         viewBot.setFocus();
index 1eed618d9290ee701409c459085282878ed38368..f1e3dd133d433fbae28129c3898967bacdae56df 100644 (file)
@@ -75,15 +75,21 @@ import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 @NonNullByDefault
 public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
-    /** Thread attribute
-     * @since 2.0 */
+    /**
+     * Thread attribute
+     *
+     * @since 2.0
+     */
     public static final String PROCESSES = "Processes"; //$NON-NLS-1$
 
     /** CallStack stack-attribute */
     public static final String CALL_STACK = "CallStack"; //$NON-NLS-1$
 
-    /** Undefined process ID
-     * @since 2.0 */
+    /**
+     * Undefined process ID
+     *
+     * @since 2.0
+     */
     protected static final int UNDEFINED_PID = -1;
 
     /** Undefined function exit name */
@@ -92,9 +98,6 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
     /** CallStack state system ID */
     private static final String ID = "org.eclipse.linuxtools.tmf.callstack"; //$NON-NLS-1$
 
-    /** Dummy function name for when no function is expected */
-    private static final String NO_FUNCTION = "no function"; //$NON-NLS-1$
-
     /**
      * Default constructor
      *
@@ -115,7 +118,7 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
 
         try {
             /* Check if the event is a function entry */
-            String functionEntryName = functionEntry(event);
+            ITmfStateValue functionEntryName = functionEntry(event);
             if (functionEntryName != null) {
                 long timestamp = event.getTimestamp().toNanos();
                 int pid = getProcessId(event);
@@ -126,31 +129,28 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
                 ss.updateOngoingState(TmfStateValue.newValueLong(threadId), threadQuark);
 
                 int callStackQuark = ss.getQuarkRelativeAndAdd(threadQuark, CALL_STACK);
-                ITmfStateValue value = TmfStateValue.newValueString(functionEntryName);
+                ITmfStateValue value = functionEntryName;
                 ss.pushAttribute(timestamp, value, callStackQuark);
                 return;
             }
 
             /* Check if the event is a function exit */
-            String functionExitName = functionExit(event);
-            if (functionExitName != null) {
+            ITmfStateValue functionExitState = functionExit(event);
+            if (functionExitState != null) {
                 long timestamp = event.getTimestamp().toNanos();
                 int pid = getProcessId(event);
                 String thread = getThreadName(event);
                 int quark = ss.getQuarkAbsoluteAndAdd(PROCESSES, Integer.toString(pid), thread, CALL_STACK);
                 ITmfStateValue poppedValue = ss.popAttribute(timestamp, quark);
-                String poppedName = (poppedValue == null ? NO_FUNCTION : poppedValue.unboxStr());
-
                 /*
                  * Verify that the value we are popping matches the one in the
                  * event field, unless the latter is undefined.
                  */
-                if (!functionExitName.equals(UNDEFINED) &&
-                        !functionExitName.equals(poppedName)) {
+                if (!functionExitState.isNull() && !functionExitState.equals(poppedValue)) {
                     Activator.logWarning(NLS.bind(
                             Messages.CallStackStateProvider_UnmatchedPoppedValue,
-                            functionExitName,
-                            poppedName));
+                            functionExitState,
+                            poppedValue));
                 }
             }
 
@@ -185,20 +185,23 @@ public abstract class CallStackStateProvider extends AbstractTmfStateProvider {
      *
      * @param event
      *            An event to check for function entry
-     * @return The function name of the function entry, or null if not a
-     *         function entry.
+     * @return The state value representing the function being entered, or null
+     *         if not a function entry
+     * @since 2.0
      */
-    protected abstract @Nullable String functionEntry(ITmfEvent event);
+    protected abstract @Nullable ITmfStateValue functionEntry(ITmfEvent event);
 
     /**
      * Check an event if it indicates a function exit.
      *
      * @param event
      *            An event to check for function exit
-     * @return The function name, or UNDEFINED, for a function exit, or null if
-     *         not a function exit.
+     * @return The state value representing the function being exited, or
+     *         TmfStateValue#nullValue() if the exited function is undefined,
+     *         or null if not a function exit.
+     * @since 2.0
      */
-    protected abstract @Nullable String functionExit(ITmfEvent event);
+    protected abstract @Nullable ITmfStateValue functionExit(ITmfEvent event);
 
     /**
      * Return the process ID of a function entry event.
index 885b3568f964ae6ac34f838d348a8f625f6acfec..643e38ee003390adf3b3cdb5953a159966359a3d 100644 (file)
@@ -857,10 +857,10 @@ public class CallStackView extends AbstractTimeGraphView {
                     // ignore
                 }
             } else if (nameValue.getType() == Type.INTEGER) {
-                name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
+                name = "0x" + Integer.toUnsignedString(nameValue.unboxInt(), 16); //$NON-NLS-1$
                 address = nameValue.unboxInt();
             } else if (nameValue.getType() == Type.LONG) {
-                name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
+                name = "0x" + Long.toUnsignedString(nameValue.unboxLong(), 16); //$NON-NLS-1$
                 address = nameValue.unboxLong();
             }
         } catch (StateValueTypeException e) {
This page took 0.030718 seconds and 5 git commands to generate.