Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Montplaisir2012-11-08 16:15:35 +0000
committerAlexandre Montplaisir2012-11-16 21:41:46 +0000
commite5e819002ff676dc0e865263861336f878b205f4 (patch)
tree3e21a04611c43899412ac5eec5b4af1e3237d96f
parentd95ac9a196ab8a2e70e853f0de1613cfcfc16627 (diff)
downloadorg.eclipse.linuxtools-e5e819002ff676dc0e865263861336f878b205f4.tar.gz
org.eclipse.linuxtools-e5e819002ff676dc0e865263861336f878b205f4.tar.xz
org.eclipse.linuxtools-e5e819002ff676dc0e865263861336f878b205f4.zip
tmf: Add the Histogram query API to ITmfStatistics
See the added Javadoc for the complete description. This will allow the Histogram view to easily plug into the trace's ITmfStatistics object to get its information (so it can be optimized for each trace type, etc.) Change-Id: Ib94aeaa369a8bf40da5246825152e26326a45e92 Signed-off-by: Alexandre Montplaisir <alexmonthy@voxpopuli.im> Reviewed-on: https://git.eclipse.org/r/8675 Tested-by: Hudson CI Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com> IP-Clean: Matthew Khouzam <matthew.khouzam@ericsson.com> Tested-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/statistics/TmfStatisticsTest.java63
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/ITmfStatistics.java24
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfEventsStatistics.java82
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfStateStatistics.java98
4 files changed, 241 insertions, 26 deletions
diff --git a/lttng/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/statistics/TmfStatisticsTest.java b/lttng/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/statistics/TmfStatisticsTest.java
index bc571de161..3c2d28aefb 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/statistics/TmfStatisticsTest.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core.tests/src/org/eclipse/linuxtools/tmf/core/tests/statistics/TmfStatisticsTest.java
@@ -14,6 +14,7 @@ package org.eclipse.linuxtools.tmf.core.tests.statistics;
import static org.junit.Assert.assertEquals;
+import java.util.List;
import java.util.Map;
import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics;
@@ -47,6 +48,68 @@ public abstract class TmfStatisticsTest {
// ------------------------------------------------------------------------
+ // Tests for histogramQuery()
+ // ------------------------------------------------------------------------
+
+ /**
+ * Test the {@link ITmfStatistics#histogramQuery} method for the small known
+ * interval.
+ */
+ @Test
+ public void testHistogramQuerySmall() {
+ final int NB_REQ = 10;
+ List<Long> results = backend.histogramQuery(t1, t6, NB_REQ);
+
+ /* Make sure the returned array has the right size */
+ assertEquals(NB_REQ, results.size());
+
+ /* Check the contents of each "bucket" */
+ assertEquals(0, results.get(0).longValue());
+ assertEquals(0, results.get(1).longValue());
+ assertEquals(0, results.get(2).longValue());
+ assertEquals(0, results.get(3).longValue());
+ assertEquals(1, results.get(4).longValue());
+ assertEquals(0, results.get(5).longValue());
+ assertEquals(0, results.get(6).longValue());
+ assertEquals(0, results.get(7).longValue());
+ assertEquals(0, results.get(8).longValue());
+ assertEquals(1, results.get(9).longValue());
+
+ }
+
+ /**
+ * Test the {@link ITmfStatistics#histogramQuery} method over the whole
+ * trace.
+ */
+ @Test
+ public void testHistogramQueryFull() {
+ final int NB_REQ = 10;
+ List<Long> results = backend.histogramQuery(tStart, tEnd, NB_REQ);
+
+ /* Make sure the returned array has the right size */
+ assertEquals(NB_REQ, results.size());
+
+ /* Check the total number of events */
+ long count = 0;
+ for (Long val : results) {
+ count += val;
+ }
+ assertEquals(totalNbEvents, count);
+
+ /* Check the contents of each "bucket" */
+ assertEquals(94161, results.get(0).longValue());
+ assertEquals(87348, results.get(1).longValue());
+ assertEquals(58941, results.get(2).longValue());
+ assertEquals(59879, results.get(3).longValue());
+ assertEquals(66941, results.get(4).longValue());
+ assertEquals(68939, results.get(5).longValue());
+ assertEquals(72746, results.get(6).longValue());
+ assertEquals(60749, results.get(7).longValue());
+ assertEquals(61208, results.get(8).longValue());
+ assertEquals(64407, results.get(9).longValue());
+ }
+
+ // ------------------------------------------------------------------------
// Test for getEventsTotal()
// ------------------------------------------------------------------------
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/ITmfStatistics.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/ITmfStatistics.java
index 46747496dd..4d6900fedc 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/ITmfStatistics.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/ITmfStatistics.java
@@ -12,6 +12,7 @@
package org.eclipse.linuxtools.tmf.core.statistics;
+import java.util.List;
import java.util.Map;
import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
@@ -53,6 +54,29 @@ public interface ITmfStatistics {
public void updateStats(boolean isGlobal, long start, long end);
/**
+ * Run a histogram query on the statistics back-end. This means, return the
+ * total number of events in a series of 'nb' equal-sized ranges between
+ * 'start' and 'end'. As its name implies, this is typically used to fill
+ * the histogram data (where each range represents one pixel on the
+ * histogram).
+ *
+ * Unlike {@link #updateStats}, this method will block the caller until the
+ * results are returned, so it should not be called from a signal handler or
+ * from the UI thread.
+ *
+ * @param start
+ * Start time of the query
+ * @param end
+ * End time of the query
+ * @param nb
+ * The number of ranges to separate the complete time range into.
+ * It will be the size() of the returned array.
+ * @return The array representing the number of events found in each
+ * sub-range.
+ */
+ public List<Long> histogramQuery(long start, long end, int nb);
+
+ /**
* Return the total number of events in the trace.
*
* @return The total number of events
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfEventsStatistics.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfEventsStatistics.java
index 0f8c18c935..4bd9e4dc3d 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfEventsStatistics.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfEventsStatistics.java
@@ -12,8 +12,12 @@
package org.eclipse.linuxtools.tmf.core.statistics;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.TreeMap;
import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
@@ -128,6 +132,25 @@ public class TmfEventsStatistics implements ITmfStatistics {
return;
}
+ @Override
+ public List<Long> histogramQuery(long start, long end, int nb) {
+ final long[] borders = new long[nb];
+ final long increment = (end - start) / nb;
+
+ long curTime = start;
+ for (int i = 0; i < nb; i++) {
+ borders[i] = curTime;
+ curTime += increment;
+ }
+
+ HistogramQueryRequest req = new HistogramQueryRequest(borders, end);
+ sendAndWait(req);
+
+ List<Long> results = new LinkedList<Long>(req.getResults());
+ return results;
+
+ }
+
private synchronized void cancelOngoingRequests() {
if (totalRequest != null && totalRequest.isRunning()) {
totalRequest.cancel();
@@ -260,4 +283,63 @@ public class TmfEventsStatistics implements ITmfStatistics {
}
}
+ /**
+ * Event request for histogram queries. It is much faster to do one event
+ * request then set the results accordingly than doing thousands of them one
+ * by one.
+ */
+ private class HistogramQueryRequest extends TmfEventRequest {
+
+ /** Map of <borders, number of events> */
+ private final TreeMap<Long, Long> results;
+
+ /**
+ * New histogram request
+ *
+ * @param borders
+ * The array of borders (not including the end time). The
+ * first element should be the start time of the queries.
+ * @param endTime
+ * The end time of the query. Not used in the results map,
+ * but we need to know when to stop the event request.
+ */
+ public HistogramQueryRequest(long[] borders, long endTime) {
+ super(trace.getEventType(),
+ new TmfTimeRange(
+ new TmfTimestamp(borders[0], SCALE),
+ new TmfTimestamp(endTime, SCALE)),
+ TmfDataRequest.ALL_DATA,
+ trace.getCacheSize(),
+ ITmfDataRequest.ExecutionType.BACKGROUND);
+
+ /* Prepare the results map, with all counts at 0 */
+ results = new TreeMap<Long, Long>();
+ for (long border : borders) {
+ results.put(border, 0L);
+ }
+ }
+
+ public Collection<Long> getResults() {
+ return results.values();
+ }
+
+ @Override
+ public void handleData(ITmfEvent event) {
+ super.handleData(event);
+ if ((event != null) && (event.getTrace() == trace)) {
+ long ts = event.getTimestamp().normalize(0, SCALE).getValue();
+ Long key = results.floorKey(ts);
+ if (key != null) {
+ incrementValue(key);
+ }
+ }
+ }
+
+ private void incrementValue(Long key) {
+ long value = results.get(key);
+ value++;
+ results.put(key, value);
+ }
+ }
+
}
diff --git a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfStateStatistics.java b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfStateStatistics.java
index 024529f22e..c33a53d419 100644
--- a/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfStateStatistics.java
+++ b/lttng/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/statistics/TmfStateStatistics.java
@@ -14,6 +14,7 @@ package org.eclipse.linuxtools.tmf.core.statistics;
import java.io.File;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -45,7 +46,6 @@ import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
* @author Alexandre Montplaisir
* @since 2.0
*/
-
public class TmfStateStatistics implements ITmfStatistics {
/** ID for the statistics state system */
@@ -157,7 +157,44 @@ public class TmfStateStatistics implements ITmfStatistics {
};
statsThread.start();
return;
+ }
+
+ @Override
+ public List<Long> histogramQuery(final long start, final long end, final int nb) {
+ final List<Long> list = new LinkedList<Long>();
+ final long increment = (end - start) / nb;
+
+ /* Wait until the history building completed */
+ if (!stats.waitUntilBuilt()) {
+ return null;
+ }
+
+ /*
+ * We will do one state system query per "border", and save the
+ * differences between each border.
+ */
+ long prevTotal = (start == stats.getStartTime()) ? 0 : getEventCountAt(start);
+ long curTime = start + increment;
+
+ long curTotal, count;
+ for (int i = 0; i < nb - 1; i++) {
+ curTotal = getEventCountAt(curTime);
+ count = curTotal - prevTotal;
+ list.add(count);
+
+ curTime += increment;
+ prevTotal = curTotal;
+ }
+
+ /*
+ * For the last bucket, we'll stretch its end time to the end time of
+ * the requested range, in case it got truncated down.
+ */
+ curTotal = getEventCountAt(end);
+ count = curTotal - prevTotal;
+ list.add(count);
+ return list;
}
@Override
@@ -228,33 +265,19 @@ public class TmfStateStatistics implements ITmfStatistics {
// end time, and answer as soon as possible...
stats.waitUntilBuilt();
- int countAtStart = 0, countAtEnd = 0;
- long startTime = checkStartTime(start);
- long endTime = checkEndTime(end);
-
- try {
- final int quark = stats.getQuarkAbsolute(Attributes.TOTAL);
- if (startTime == stats.getStartTime()) {
- countAtStart = 0;
- } else {
- /* State system works that way... */
- countAtStart = stats.querySingleState(startTime - 1, quark).getStateValue().unboxInt();
- }
- countAtEnd = stats.querySingleState(endTime, quark).getStateValue().unboxInt();
-
- } catch (TimeRangeException e) {
- /* Assume there is no events for that range */
- return 0;
- } catch (AttributeNotFoundException e) {
- e.printStackTrace();
- } catch (StateValueTypeException e) {
- e.printStackTrace();
- } catch (StateSystemDisposedException e) {
- e.printStackTrace();
+ long startCount;
+ if (start == stats.getStartTime()) {
+ startCount = 0;
+ } else {
+ /*
+ * We want the events happening at "start" to be included, so we'll
+ * need to query one unit before that point.
+ */
+ startCount = getEventCountAt(start - 1);
}
+ long endCount = getEventCountAt(end);
- long total = countAtEnd - countAtStart;
- return total;
+ return endCount - startCount;
}
@Override
@@ -329,6 +352,29 @@ public class TmfStateStatistics implements ITmfStatistics {
return map;
}
+ private long getEventCountAt(long timestamp) {
+ /* Make sure the target time is within the range of the history */
+ long ts = checkStartTime(timestamp);
+ ts = checkEndTime(ts);
+
+ try {
+ final int quark = stats.getQuarkAbsolute(Attributes.TOTAL);
+ long count = stats.querySingleState(ts, quark).getStateValue().unboxInt();
+ return count;
+
+ } catch (TimeRangeException e) {
+ /* Assume there is no events for that range */
+ } catch (AttributeNotFoundException e) {
+ e.printStackTrace();
+ } catch (StateValueTypeException e) {
+ e.printStackTrace();
+ } catch (StateSystemDisposedException e) {
+ e.printStackTrace();
+ }
+
+ return 0;
+ }
+
private long checkStartTime(long initialStart) {
long start = initialStart;
if (start < stats.getStartTime()) {

Back to the top