import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis;
import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statistics.SystemCallLatencyStatisticsAnalysisModule;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
public void testSmallTraceSequential() {
final SystemCallLatencyStatisticsAnalysisModule syscallStatsModule = fSyscallStatsModule;
assertNotNull(syscallStatsModule);
- SegmentStoreStatistics totalStats = syscallStatsModule.getTotalStats();
+ IStatistics<@NonNull ISegment> totalStats = syscallStatsModule.getStatsTotal();
assertNotNull(totalStats);
- assertEquals(1801, totalStats.getNbSegments());
+ assertEquals(1801, totalStats.getNbElements());
assertEquals(5904091700L, totalStats.getMax());
}
}
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsView;
import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics.SystemCallLatencyStatisticsView;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers;
assertNotNull(os);
IViewPart viewPart = view.getReference().getView(true);
assertTrue(viewPart instanceof SystemCallLatencyStatisticsView);
- Class<@NonNull AbstractSegmentStoreStatisticsView> clazz = AbstractSegmentStoreStatisticsView.class;
+ Class<@NonNull AbstractSegmentsStatisticsView> clazz = AbstractSegmentsStatisticsView.class;
Method method = clazz.getDeclaredMethod("exportToTsv", java.io.OutputStream.class);
method.setAccessible(true);
final Exception[] except = new Exception[1];
package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsView;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
/**
* View to display latency statistics.
* @author Bernd Hufmann
*
*/
-public class SystemCallLatencyStatisticsView extends AbstractSegmentStoreStatisticsView {
+public class SystemCallLatencyStatisticsView extends AbstractSegmentsStatisticsView {
/** The view ID*/
public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.ui.views.latency.statsview"; //$NON-NLS-1$
@Override
- protected AbstractSegmentStoreStatisticsViewer createSegmentStoreStatisticsViewer(Composite parent) {
+ protected AbstractTmfTreeViewer createSegmentStoreStatisticsViewer(Composite parent) {
return new SystemCallLatencyStatisticsViewer(parent);
}
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsViewer;
import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.statistics.SystemCallLatencyStatisticsAnalysisModule;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
* @author Bernd Hufmann
*
*/
-public class SystemCallLatencyStatisticsViewer extends AbstractSegmentStoreStatisticsViewer {
+public class SystemCallLatencyStatisticsViewer extends AbstractSegmentsStatisticsViewer {
private static final String SYSCALL_LEVEL = checkNotNull(Messages.LatencyStatistics_SyscallLevelName);
org.eclipse.tracecompass.tmf.ctf.core,
org.eclipse.tracecompass.tmf.ctf.core.tests,
org.eclipse.core.resources,
- org.eclipse.tracecompass.analysis.timing.core;bundle-version="1.0.0"
+ org.eclipse.tracecompass.analysis.timing.core
Import-Package: com.google.common.collect,
- org.eclipse.tracecompass.testtraces.ctf;version="1.0.0"
+ org.eclipse.tracecompass.testtraces.ctf
Export-Package: org.eclipse.tracecompass.analysis.timing.core.tests,
org.eclipse.tracecompass.analysis.timing.core.tests.callgraph,
org.eclipse.tracecompass.analysis.timing.core.tests.flamegraph,
- org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics
+ org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics,
+ org.eclipse.tracecompass.analysis.timing.core.tests.statistics
Bundle-Activator: org.eclipse.tracecompass.analysis.timing.core.tests.Activator
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub;
public void testTotalStats() throws TmfAnalysisException {
TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
- SegmentStoreStatistics totalStats = fixture.getTotalStats();
+ IStatistics<@NonNull ISegment> totalStats = fixture.getStatsTotal();
assertNotNull(totalStats);
// no need to test the content much as it is tested in the other test.
- assertEquals(StubSegmentStatisticsAnalysis.SIZE, totalStats.getNbSegments());
+ assertEquals(StubSegmentStatisticsAnalysis.SIZE, totalStats.getNbElements());
trace.dispose();
fixture.dispose();
}
public void testPerTypeStats() throws TmfAnalysisException {
TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
- Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = fixture.getPerSegmentTypeStats();
+ Map<@NonNull String, IStatistics<@NonNull ISegment>> perTypeStats = fixture.getStatsPerType();
assertNotNull(perTypeStats);
// no need to test the content much as it is tested in the other test.
assertEquals(2, perTypeStats.size());
assertEquals(ImmutableSet.<String> of("odd", "even"), perTypeStats.keySet());
- SegmentStoreStatistics segmentStoreStatistics = perTypeStats.get("even");
+ IStatistics<@NonNull ISegment> segmentStoreStatistics = perTypeStats.get("even");
assertNotNull(segmentStoreStatistics);
// starts with 0 so size + 1
- assertEquals(StubSegmentStatisticsAnalysis.SIZE / 2 + 1, segmentStoreStatistics.getNbSegments());
+ assertEquals(StubSegmentStatisticsAnalysis.SIZE / 2 + 1, segmentStoreStatistics.getNbElements());
trace.dispose();
fixture.dispose();
}
public void testPartialStats() throws TmfAnalysisException {
TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
- SegmentStoreStatistics totalStats = fixture.getTotalStatsForRange(100, 1100, new NullProgressMonitor());
+ IStatistics<@NonNull ISegment> totalStats = fixture.getStatsForRange(100, 1100, new NullProgressMonitor());
assertNotNull(totalStats);
// no need to test the content much as it is tested in the other test.
// 1051 = 1001 where start is between start and end + 50 overlapping
// start
- assertEquals(1051, totalStats.getNbSegments());
+ assertEquals(1051, totalStats.getNbElements());
trace.dispose();
fixture.dispose();
}
public void testPartialPerTypeStats() throws TmfAnalysisException {
TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
- Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = fixture.getPerSegmentTypeStatsForRange(100, 1100, new NullProgressMonitor());
+ Map<@NonNull String, IStatistics<@NonNull ISegment>> perTypeStats = fixture.getStatsPerTypeForRange(100, 1100, new NullProgressMonitor());
assertNotNull(perTypeStats);
// no need to test the content much as it is tested in the other test.
assertEquals(2, perTypeStats.size());
assertEquals(ImmutableSet.<String> of("odd", "even"), perTypeStats.keySet());
- SegmentStoreStatistics segmentStoreStatistics = perTypeStats.get("even");
+ IStatistics<@NonNull ISegment> segmentStoreStatistics = perTypeStats.get("even");
assertNotNull(segmentStoreStatistics);
// 526 = 1051/2+1 = see explanation of 1051 in #testPartialStats
- assertEquals(526, segmentStoreStatistics.getNbSegments());
+ assertEquals(526, segmentStoreStatistics.getNbElements());
trace.dispose();
fixture.dispose();
}
StubSegmentStatisticsAnalysis fixture = getValidSegmentStats(trace);
NullProgressMonitor monitor = new NullProgressMonitor();
monitor.setCanceled(true);
- Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = fixture.getPerSegmentTypeStatsForRange(100, 1100, monitor);
+ Map<@NonNull String, IStatistics<@NonNull ISegment>> perTypeStats = fixture.getStatsPerTypeForRange(100, 1100, monitor);
assertEquals(Collections.emptyMap(), perTypeStats);
trace.dispose();
fixture.dispose();
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2016 Ericsson
- *
- * 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.tracecompass.analysis.timing.core.tests.segmentstore.statistics;
-
-import java.util.Collection;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.segmentstore.core.ISegment;
-
-/**
- * This calculates the statistics of a segment store in an offline manner to
- * validate online calculations.
- *
- * @author Matthew Khouzam
- *
- */
-public class OfflineStatisticsCalculator {
- private final Collection<@NonNull ISegment> fSs;
-
- /**
- * Constructor
- *
- * @param ss
- * segment store, fully build
- */
- public OfflineStatisticsCalculator(Collection<@NonNull ISegment> ss) {
- fSs = ss;
- }
-
- /**
- * Get the max value
- *
- * @return the max value
- */
- public long getMax() {
- long max = Long.MIN_VALUE;
- for (ISegment interval : fSs) {
- max = Math.max(max, interval.getLength());
- }
- return max;
- }
-
- /**
- * Get the min value
- *
- * @return the min value
- */
- public long getMin() {
- long min = Long.MAX_VALUE;
- for (ISegment interval : fSs) {
- min = Math.min(min, interval.getLength());
- }
- return min;
- }
-
- /**
- * Get the average value
- *
- * @return the average value
- */
- public double getAvg() {
- double total = 0;
- for (ISegment interval : fSs) {
- total += (double) interval.getLength() / (double) fSs.size();
- }
- return total;
- }
-
- /**
- * Get the standard deviation.
- *
- * @return the standard deviation
- */
- public double getStdDev() {
- if (fSs.size() < 3) {
- return Double.NaN;
- }
- double mean = getAvg();
-
- double totalVariance = 0;
- for (ISegment interval : fSs) {
- double result = interval.getLength() - mean;
- totalVariance += result * result / (fSs.size() - 1);
- }
- return Math.sqrt(totalVariance);
- }
-
- /**
- * Get the total
- *
- * @return the total
- */
- public long getTotal() {
- long total = 0;
- for (ISegment interval : fSs) {
- total += interval.getLength();
- }
- return total;
- }
-
- /**
- * Get the # of intervals
- * @return the # of intervals
- */
- public int count() {
- return fSs.size();
- }
-}
package org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore.statistics;
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
import java.util.Random;
+import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.tests.statistics.AbstractStatisticsTest;
import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
-import org.junit.Test;
/**
- * Test the segment store statistics calculations. This is done with two tests.
- * <ol>
- * <li>test the values vs some sample points calculated by hand (sanity test)
- * </li>
- * <li>2- test exhaustively vs a reference implementation.</li>
- * </ol>
+ * Test statistics for segment length
*
* @author Matthew Khouzam
*/
-public class SegmentStoreStatisticsTest {
-
- private static final int MEDIUM_AMOUNT_OF_SEGMENTS = 100;
- private static final int LARGE_AMOUNT_OF_SEGMENTS = 1000000;
-
- private static final double NO_ERROR = 0.0;
- private static final double ERROR = 0.000001;
- private static final double APPROX_ERROR = 0.0001;
-
- private static void testOnlineVsOffline(List<@NonNull ISegment> fixture) {
- validate(new OfflineStatisticsCalculator(fixture), getSegStoreStat(fixture));
- }
-
- /**
- * Test incrementing
- */
- @Test
- public void climbTest() {
- List<@NonNull ISegment> fixture = new ArrayList<>(MEDIUM_AMOUNT_OF_SEGMENTS);
- for (int i = 0; i < MEDIUM_AMOUNT_OF_SEGMENTS; i++) {
- fixture.add(createDummySegment(i, i * 2));
- }
- SegmentStoreStatistics sss = getSegStoreStat(fixture);
- assertEquals("Average", 49.5, sss.getAverage(), ERROR);
- assertEquals("Min", 0, sss.getMin());
- assertEquals("Max", 99, sss.getMax());
- assertEquals("Standard Deviation", 29.0, sss.getStdDev(), 0.02);
- assertEquals("Min Segment", 0, sss.getMinSegment().getLength());
- assertEquals("Max Segment", 99, sss.getMaxSegment().getLength());
- testOnlineVsOffline(fixture);
- }
-
- private static SegmentStoreStatistics getSegStoreStat(List<@NonNull ISegment> fixture) {
- SegmentStoreStatistics sss = new SegmentStoreStatistics();
- for (ISegment seg : fixture) {
- sss.update(seg);
- }
- return sss;
- }
-
- /**
- * Test with segments of decrementing size
- */
- @Test
- public void decrementingTest() {
- List<@NonNull ISegment> fixture = new ArrayList<>(MEDIUM_AMOUNT_OF_SEGMENTS);
- for (int i = MEDIUM_AMOUNT_OF_SEGMENTS; i >= 0; i--) {
- fixture.add(createDummySegment(i, i * 2));
- }
- SegmentStoreStatistics sss = getSegStoreStat(fixture);
- assertEquals("Average", 50, sss.getAverage(), NO_ERROR);
- assertEquals("Min", 0, sss.getMin());
- assertEquals("Max", 100, sss.getMax());
- assertEquals("Standard Deviation", 29.3, sss.getStdDev(), 0.01);
- assertEquals("Min Segment", 0, sss.getMinSegment().getLength());
- assertEquals("Max Segment", 100, sss.getMaxSegment().getLength());
- testOnlineVsOffline(fixture);
- }
-
- /**
- * Test a data set with a small number of segments
- */
- @Test
- public void smallTest() {
- List<@NonNull ISegment> fixture = new ArrayList<>();
- for (int i = 1; i >= 0; i--) {
- fixture.add(createDummySegment(i, i * 2));
- }
- testOnlineVsOffline(fixture);
- }
-
- /**
- * Test a data set with a large number of segments
- */
- @Test
- public void largeTest() {
- List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
- for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) {
- fixture.add(createDummySegment(i, i * 2));
- }
- testOnlineVsOffline(fixture);
- }
-
- /**
- * Test a random dataset where the distribution follows white noise
- */
- @Test
- public void noiseTest() {
- Random rnd = new Random();
- rnd.setSeed(1234);
- List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
- for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) {
- int start = Math.abs(rnd.nextInt(100000000));
- int end = start + Math.abs(rnd.nextInt(1000000));
- fixture.add(createDummySegment(start, end));
- }
- testOnlineVsOffline(fixture);
- }
-
- /**
- * Test a random dataset where the distribution follows gaussian noise
- */
- @Test
- public void gaussianNoiseTest() {
- Random rnd = new Random();
- rnd.setSeed(1234);
- List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
- for (int i = 1; i <= LARGE_AMOUNT_OF_SEGMENTS; i++) {
- int start = Math.abs(rnd.nextInt(100000000));
- final int delta = Math.abs(rnd.nextInt(1000));
- int end = start + delta * delta;
- fixture.add(createDummySegment(start, end));
- }
- testOnlineVsOffline(fixture);
- }
+public class SegmentStoreStatisticsTest extends AbstractStatisticsTest<@NonNull ISegment> {
- /**
- * Test building a statistics store with streams
- */
- @Test
- public void streamBuildingTest() {
- SegmentStoreStatistics expected = new SegmentStoreStatistics();
- List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
- for (long i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
- fixture.add(new BasicSegment(i, i + 2));
- }
- fixture.forEach(e -> expected.update(e));
- SegmentStoreStatistics actual = fixture.stream()
- .<@NonNull SegmentStoreStatistics> collect(SegmentStoreStatistics::new, SegmentStoreStatistics::update, SegmentStoreStatistics::merge);
- validate(expected, actual);
- }
+ private final Random fRandom = new Random(10);
/**
- * Test building a statistics store with parallel streams
+ * Constructor
*/
- @Test
- public void parallelStreamBuildingTest() {
- SegmentStoreStatistics expected = new SegmentStoreStatistics();
- List<@NonNull ISegment> fixture = new ArrayList<>(LARGE_AMOUNT_OF_SEGMENTS);
- for (long i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
- fixture.add(new BasicSegment(i, i + 2));
- }
- fixture.forEach(e -> expected.update(e));
- SegmentStoreStatistics actual = fixture.parallelStream()
- .<@NonNull SegmentStoreStatistics> collect(SegmentStoreStatistics::new, SegmentStoreStatistics::update, SegmentStoreStatistics::merge);
- validate(expected, actual);
+ public SegmentStoreStatisticsTest() {
+ super(s -> s.getLength());
}
- /**
- * Test statistics nodes being merged. Two contiguous blocks.
- */
- @Test
- public void mergeStatisticsNodesTest() {
- // calculates stats for all the segments
- SegmentStoreStatistics expected = new SegmentStoreStatistics();
- // calculates stats for half of the segments
- SegmentStoreStatistics a = new SegmentStoreStatistics();
- // calculates stats for another half of the segments
- SegmentStoreStatistics b = new SegmentStoreStatistics();
- List<@NonNull ISegment> fixture = new ArrayList<>();
- for (int i = 0; i < 10; i++) {
- ISegment seg = new BasicSegment(i, i * 2 + 2);
- expected.update(seg);
- a.update(seg);
- fixture.add(seg);
- }
- for (int i = 0; i < 10; i++) {
- ISegment seg = new BasicSegment(i, i * 2 + 2);
- expected.update(seg);
- b.update(seg);
- fixture.add(seg);
- }
- a.merge(b);
- OfflineStatisticsCalculator offlineExpected = new OfflineStatisticsCalculator(fixture);
- // Compare the expected stats with the offline algorithm
- validate(offlineExpected, expected);
- // Compare the results of the merge with the expected results
- validate(expected, a);
- }
+ @Override
+ protected Collection<@NonNull ISegment> createElementsWithValues(Collection<@NonNull Long> longFixture) {
+ return longFixture.stream()
+ .map(l -> {
+ long nextStart = fRandom.nextInt(10000000);
+ long nextEnd = nextStart + l;
+ // Check the boundaries, it is random after all, so if
+ // there's an overflow, just take the max value as end time
+ if (nextEnd < nextStart) {
+ nextEnd = Long.MAX_VALUE;
+ nextStart = nextEnd - l;
+ }
+ return new BasicSegment(nextStart, nextEnd);
+ })
+ .collect(Collectors.toList());
- /**
- * Test statistics nodes being merged. Two random blocks.
- */
- @Test
- public void mergeStatisticsRandomNodesTest() {
- // calculates stats for all the segments
- SegmentStoreStatistics expected = new SegmentStoreStatistics();
- // calculates stats for half of the segments, randomly
- SegmentStoreStatistics a = new SegmentStoreStatistics();
- // calculates stats for the other half of the segments
- SegmentStoreStatistics b = new SegmentStoreStatistics();
- List<@NonNull ISegment> fixture = new ArrayList<>();
- Random rnd = new Random();
- rnd.setSeed(10);
- int size = rnd.nextInt(1000);
- int size2 = rnd.nextInt(1000);
- for (int i = 0; i < size; i++) {
- int start = Math.abs(rnd.nextInt(100000000));
- final int delta = Math.abs(rnd.nextInt(1000));
- int end = start + delta * delta;
- ISegment seg = new BasicSegment(start, end);
- expected.update(seg);
- a.update(seg);
- fixture.add(seg);
- }
- for (int i = 0; i < size2; i++) {
- int start = Math.abs(rnd.nextInt(100000000));
- final int delta = Math.abs(rnd.nextInt(1000));
- int end = start + delta * delta;
- ISegment seg = new BasicSegment(start, end);
- expected.update(seg);
- b.update(seg);
- fixture.add(seg);
- }
- a.merge(b);
- assertEquals(size + size2, a.getNbSegments());
- OfflineStatisticsCalculator offlineExpected = new OfflineStatisticsCalculator(fixture);
- // Compare the expected stats with the offline algorithm
- validate(offlineExpected, expected);
- // Compare the results of the merge with the expected results
- validate(expected, a);
}
- /**
- * Test statistics nodes being merged. Two overlapping blocks.
- */
- @Test
- public void mergeStatisticsOverlappingNodesTest() {
- // calculates stats for all the segments
- SegmentStoreStatistics expected = new SegmentStoreStatistics();
- // calculates stats for half of the segments
- SegmentStoreStatistics a = new SegmentStoreStatistics();
- // calculates stats for the other half of the segments
- SegmentStoreStatistics b = new SegmentStoreStatistics();
- List<@NonNull ISegment> fixture = new ArrayList<>();
- for (int i = 0; i < 100; i++) {
- BasicSegment seg = new BasicSegment(i, i * 2 + 2);
- expected.update(seg);
- if ((i & 2) != 0) {
- a.update(seg);
- } else {
- b.update(seg);
- }
- fixture.add(seg);
- }
- a.merge(b);
- OfflineStatisticsCalculator offlineExpected = new OfflineStatisticsCalculator(fixture);
- validate(offlineExpected, expected);
- validate(expected, a);
+ @Override
+ public void testLimitDataset2() {
+ /* ISegments do not support negative values */
}
- private static @NonNull SegmentStoreStatistics fillSmallStatistics() {
- SegmentStoreStatistics stats = new SegmentStoreStatistics();
- for (int i = 0; i < 10; i++) {
- BasicSegment seg = new BasicSegment(i, i * 2 + 2);
- stats.update(seg);
- }
- return stats;
+ @Override
+ public void testLargeDatasetNegative() {
+ /* ISegments do not support negative values */
}
- /**
- * Test corner cases when merging statistics nodes
- */
- @Test
- public void mergeStatisticsCornerCaseNodesTest() {
- ISegment segment = new BasicSegment(1, 5);
-
- // Control statistics, not to be modified
- SegmentStoreStatistics noSegments = new SegmentStoreStatistics();
- SegmentStoreStatistics oneSegment = new SegmentStoreStatistics();
- oneSegment.update(segment);
-
- // The segment store statistics to test
- SegmentStoreStatistics testStats = new SegmentStoreStatistics();
- SegmentStoreStatistics testStats2 = new SegmentStoreStatistics();
-
- // Test merging empty stats on a non-empty one
- testStats.update(segment);
- testStats.merge(testStats2);
- validate(oneSegment, testStats);
- validate(noSegments, testStats2);
-
- // Test merging on an empty stats
- testStats2.merge(testStats);
- validate(oneSegment, testStats);
- validate(oneSegment, testStats2);
-
- // Fill a small segment store and add the one extra segment to it
- SegmentStoreStatistics expected = fillSmallStatistics();
- expected.update(segment);
-
- // Test merging stats with only 1 segment
- testStats = fillSmallStatistics();
- testStats.merge(testStats2);
- validate(oneSegment, testStats2);
- validate(expected, testStats);
-
- // Test merging on stats with only 1 segment
- testStats = fillSmallStatistics();
- testStats2.merge(testStats);
- validate(fillSmallStatistics(), testStats);
- validate(expected, testStats2);
-
- }
-
- private static void validate(SegmentStoreStatistics expected, SegmentStoreStatistics toBeTested) {
- assertEquals("# of Segments", expected.getNbSegments(), toBeTested.getNbSegments());
- assertEquals("Total duration", expected.getTotal(), toBeTested.getTotal(), ERROR * expected.getTotal());
- assertEquals("Average", expected.getAverage(), toBeTested.getAverage(), ERROR * expected.getAverage());
- assertEquals("Min", expected.getMin(), toBeTested.getMin());
- assertEquals("Max", expected.getMax(), toBeTested.getMax());
- assertEquals("Min Segment", expected.getMinSegment().getLength(), toBeTested.getMinSegment().getLength());
- assertEquals("Max Segment", expected.getMaxSegment().getLength(), toBeTested.getMaxSegment().getLength());
- assertEquals("Standard Deviation", expected.getStdDev(), toBeTested.getStdDev(), APPROX_ERROR * expected.getStdDev());
- }
-
- private static void validate(OfflineStatisticsCalculator osc, SegmentStoreStatistics sss) {
- assertEquals("# of Segments", osc.count(), sss.getNbSegments());
- assertEquals("Total duration", osc.getTotal(), sss.getTotal(), ERROR * osc.getTotal());
- assertEquals("Average", osc.getAvg(), sss.getAverage(), ERROR * osc.getAvg());
- assertEquals("Min", osc.getMin(), sss.getMin());
- assertEquals("Max", osc.getMax(), sss.getMax());
- assertEquals("Min Segment", osc.getMin(), sss.getMinSegment().getLength());
- assertEquals("Max Segment", osc.getMax(), sss.getMaxSegment().getLength());
- assertEquals("Standard Deviation", osc.getStdDev(), sss.getStdDev(), ERROR * osc.getStdDev());
- }
-
- private static @NonNull BasicSegment createDummySegment(int start, int end) {
- return new BasicSegment(start, end);
- }
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.Statistics;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
*/
public abstract class AbstractSegmentStatisticsAnalysis extends TmfAbstractAnalysisModule {
+ private static Function<ISegment, Long> FCT_LENGTH = s -> s.getLength();
+
private @Nullable ISegmentStoreProvider fSegmentStoreProviderModule;
- private @Nullable SegmentStoreStatistics fTotalStats;
+ private @Nullable IStatistics<ISegment> fTotalStats;
- private Map<String, SegmentStoreStatistics> fPerSegmentTypeStats = new HashMap<>();
+ private Map<String, IStatistics<ISegment>> fPerSegmentTypeStats = new HashMap<>();
@Override
protected Iterable<IAnalysisModule> getDependentAnalyses() {
return false;
}
- SegmentStoreStatistics totalStats = getTotalStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
+ IStatistics<ISegment> totalStats = getTotalStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
if (totalStats == null) {
return false;
}
- Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = getPerTypeStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
- if (perTypeStats == null) {
- return false;
- }
+ Map<String, IStatistics<ISegment>> perTypeStats = getPerTypeStats(TmfTimeRange.ETERNITY.getStartTime().toNanos(), TmfTimeRange.ETERNITY.getEndTime().toNanos(), monitor);
fTotalStats = totalStats;
fPerSegmentTypeStats = perTypeStats;
+
return true;
}
- private @Nullable SegmentStoreStatistics getTotalStats(long start, long end, IProgressMonitor monitor) {
+ private @Nullable IStatistics<ISegment> getTotalStats(long start, long end, IProgressMonitor monitor) {
Iterable<@NonNull ISegment> store = getSegmentStore(start, end);
if (store == null) {
return null;
* @return The total statistics, or null if segment store is not valid or if
* the request is canceled
* @since 1.2
+ * @deprecated use {@link #getStatsForRange(long, long, IProgressMonitor)} instead
*/
+ @Deprecated
public @Nullable SegmentStoreStatistics getTotalStatsForRange(long start, long end, IProgressMonitor monitor) {
+ IStatistics<@NonNull ISegment> stats = getStatsForRange(start, end, monitor);
+ return (stats == null) ? null : new SegmentStoreStatistics(stats);
+ }
+
+ /**
+ * Get the total statistics for a specific range. If the range start is
+ * TmfTimeRange.ETERNITY.getStartTime().toNanos() and the range end is
+ * TmfTimeRange.ETERNITY.getEndTime().toNanos(), it will return the
+ * statistics for the whole trace.
+ *
+ * @param start
+ * The start time of the range
+ * @param end
+ * The end time of the range
+ * @param monitor
+ * The progress monitor
+ * @return The total statistics, or null if segment store is not valid or if
+ * the request is canceled
+ * @since 1.3
+ */
+ public @Nullable IStatistics<ISegment> getStatsForRange(long start, long end, IProgressMonitor monitor) {
ITmfTrace trace = getTrace();
if (trace != null && (start == TmfTimeRange.ETERNITY.getStartTime().toNanos() && end == TmfTimeRange.ETERNITY.getEndTime().toNanos())) {
waitForCompletion();
- return getTotalStats();
+ return getStatsTotal();
}
return getTotalStats(start, end, monitor);
}
- private @Nullable Map<@NonNull String, @NonNull SegmentStoreStatistics> getPerTypeStats(long start, long end, IProgressMonitor monitor) {
+ private Map<@NonNull String, org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics<ISegment>> getPerTypeStats(long start, long end, IProgressMonitor monitor) {
Iterable<@NonNull ISegment> store = getSegmentStore(start, end);
- if (monitor.isCanceled()) {
+ if (monitor.isCanceled() || store == null) {
return Collections.EMPTY_MAP;
}
return calculateTotalPerType(store, monitor);
* @return The per segment type statistics, or null if segment store is not
* valid or if the request is canceled
* @since 1.2
+ * @deprecated use {@link #getStatsPerTypeForRange(long, long, IProgressMonitor)} instead
*/
- public @Nullable Map<@NonNull String, @NonNull SegmentStoreStatistics> getPerSegmentTypeStatsForRange(long start, long end, IProgressMonitor monitor) {
+ @Deprecated
+ public @Nullable Map<String, SegmentStoreStatistics> getPerSegmentTypeStatsForRange(long start, long end, IProgressMonitor monitor) {
+ Map<String, IStatistics<ISegment>> stats = getStatsPerTypeForRange(start, end, monitor);
+ Map<String, SegmentStoreStatistics> map = new HashMap<>();
+ for (Entry<String, IStatistics<ISegment>> entry : stats.entrySet()) {
+ map.put(entry.getKey(), new SegmentStoreStatistics(entry.getValue()));
+ }
+ return map;
+ }
+
+ /**
+ * Get the per segment type statistics for a specific range. If the range
+ * start is TmfTimeRange.ETERNITY.getStartTime().toNanos() and the range end
+ * is TmfTimeRange.ETERNITY.getEndTime().toNanos(), it will return the
+ * statistics for the whole trace.
+ *
+ * @param start
+ * The start time of the range
+ * @param end
+ * The end time of the range
+ * @param monitor
+ * The progress monitor
+ * @return The per segment type statistics, or null if segment store is not
+ * valid or if the request is canceled
+ * @since 1.3
+ */
+ public Map<@NonNull String, org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics<ISegment>> getStatsPerTypeForRange(long start, long end, IProgressMonitor monitor) {
ITmfTrace trace = getTrace();
if (trace != null && (start == TmfTimeRange.ETERNITY.getStartTime().toNanos() && end == TmfTimeRange.ETERNITY.getEndTime().toNanos())) {
waitForCompletion();
- return getPerSegmentTypeStats();
+ return getStatsPerType();
}
return getPerTypeStats(start, end, monitor);
}
: Collections.EMPTY_LIST;
}
- private static @Nullable SegmentStoreStatistics calculateTotalManual(Iterable<@NonNull ISegment> segments, IProgressMonitor monitor) {
- SegmentStoreStatistics total = new SegmentStoreStatistics();
+ private static @Nullable IStatistics<ISegment> calculateTotalManual(Iterable<@NonNull ISegment> segments, IProgressMonitor monitor) {
+ IStatistics<ISegment> total = new Statistics<>(FCT_LENGTH);
Iterator<@NonNull ISegment> iter = segments.iterator();
while (iter.hasNext()) {
if (monitor.isCanceled()) {
return total;
}
- private Map<@NonNull String, @NonNull SegmentStoreStatistics> calculateTotalPerType(Iterable<ISegment> segments, IProgressMonitor monitor) {
- Map<String, SegmentStoreStatistics> perSegmentTypeStats = new HashMap<>();
+ private Map<@NonNull String, org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics<ISegment>> calculateTotalPerType(Iterable<ISegment> segments, IProgressMonitor monitor) {
+ Map<String, IStatistics<ISegment>> perSegmentTypeStats = new HashMap<>();
Iterator<ISegment> iter = segments.iterator();
while (iter.hasNext()) {
ISegment segment = iter.next();
String segmentType = getSegmentType(segment);
if (segmentType != null) {
- SegmentStoreStatistics values = perSegmentTypeStats.get(segmentType);
+ IStatistics<ISegment> values = perSegmentTypeStats.get(segmentType);
if (values == null) {
- values = new SegmentStoreStatistics();
+ values = new Statistics<>(FCT_LENGTH);
}
values.update(segment);
perSegmentTypeStats.put(segmentType, values);
* The total statistics
*
* @return the total statistics
+ * @deprecated use {@link #getStatsTotal()} instead
*/
+ @Deprecated
public @Nullable SegmentStoreStatistics getTotalStats() {
+ IStatistics<@NonNull ISegment> totalStats = fTotalStats;
+ return totalStats == null ? null : new SegmentStoreStatistics(totalStats);
+ }
+
+ /**
+ * Get the statistics for the full segment store
+ *
+ * @return The complete statistics
+ * @since 1.3
+ */
+ public @Nullable IStatistics<ISegment> getStatsTotal() {
return fTotalStats;
}
* The per syscall statistics
*
* @return the per syscall statistics
+ * @deprecated use {@link #getStatsPerType()} instead
*/
+ @Deprecated
public @Nullable Map<String, SegmentStoreStatistics> getPerSegmentTypeStats() {
+ Map<String, SegmentStoreStatistics> map = new HashMap<>();
+ for (Entry<String, IStatistics<ISegment>> entry : fPerSegmentTypeStats.entrySet()) {
+ map.put(entry.getKey(), new SegmentStoreStatistics(entry.getValue()));
+ }
+ return map;
+ }
+
+ /**
+ * Get the statistics for each type of segment in this segment store
+ *
+ * @return the map of statistics per type
+ * @since 1.3
+ */
+ public Map<String, IStatistics<ISegment>> getStatsPerType() {
return fPerSegmentTypeStats;
}
*******************************************************************************/
package org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.Statistics;
import org.eclipse.tracecompass.segmentstore.core.BasicSegment;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
* @author Bernd Hufmann
*/
public class SegmentStoreStatistics {
- private ISegment fMin;
- private ISegment fMax;
- private long fNbSegments;
- private double fAverage;
+
+ private static final ISegment MIN_SEGMENT = new BasicSegment(0, Long.MAX_VALUE);
+ private static final ISegment MAX_SEGMENT = new BasicSegment(Long.MIN_VALUE, 0);
+
+ private final IStatistics<ISegment> fStatistics;
+
/**
- * reminder, this is the variance * nb elem, as per the online algorithm
+ * Constructor
*/
- private double fVariance;
- private double fTotal;
+ public SegmentStoreStatistics() {
+ fStatistics = new Statistics<>(s -> s.getLength());
+ }
/**
* Constructor
+ *
+ * @param stats The statistics object
+ * @since 1.3
*/
- public SegmentStoreStatistics() {
- fMin = new BasicSegment(0, Long.MAX_VALUE);
- fMax = new BasicSegment(Long.MIN_VALUE, 0);
- fNbSegments = 0;
- fAverage = 0.0;
- fVariance = 0.0;
- fTotal = 0.0;
+ public SegmentStoreStatistics(IStatistics<ISegment> stats) {
+ fStatistics = stats;
}
/**
* Get minimum value
*
* @return minimum value
+ * @since 1.2
*/
public long getMin() {
- return fMin.getLength();
+ return fStatistics.getMin();
}
/**
* @return maximum value
*/
public long getMax() {
- return fMax.getLength();
+ return fStatistics.getMax();
}
/**
* @return segment with minimum length
*/
public ISegment getMinSegment() {
- return fMin;
+ ISegment minObject = fStatistics.getMinObject();
+ return minObject == null ? MIN_SEGMENT : minObject;
}
/**
* @return segment with maximum length
*/
public ISegment getMaxSegment() {
- return fMax;
+ ISegment maxObject = fStatistics.getMaxObject();
+ return maxObject == null ? MAX_SEGMENT : maxObject;
}
/**
* @return number of segments analyzed
*/
public long getNbSegments() {
- return fNbSegments;
+ return fStatistics.getNbElements();
}
/**
* @return arithmetic average
*/
public double getAverage() {
- return fAverage;
+ return fStatistics.getMean();
}
/**
* there are less than 3 elements
*/
public double getStdDev() {
- return fNbSegments > 2 ? Math.sqrt(fVariance / (fNbSegments - 1)) : Double.NaN;
+ return fStatistics.getStdDev();
}
/**
* @since 1.1
*/
public double getTotal() {
- return fTotal;
+ return fStatistics.getTotal();
}
/**
* the segment used for the update
*/
public void update(ISegment segment) {
- long value = segment.getLength();
- /*
- * Min and max are trivial, as well as number of segments
- */
- long min = fMin.getLength();
- long max = fMax.getLength();
- fMin = min <= value ? fMin : segment;
- fMax = max >= value ? fMax : segment;
-
- fNbSegments++;
- /*
- * The running mean is not trivial, see proof in javadoc.
- */
- double delta = value - fAverage;
- fAverage += delta / fNbSegments;
- fVariance += delta * (value - fAverage);
- fTotal += value;
+ fStatistics.update(segment);
}
/**
* @since 1.2
*/
public void merge(SegmentStoreStatistics other) {
- if (other.fNbSegments == 0) {
- return;
- } else if (fNbSegments == 0) {
- copy(other);
- } else if (other.fNbSegments == 1) {
- update(other.fMax);
- } else if (fNbSegments == 1) {
- SegmentStoreStatistics copyOther = new SegmentStoreStatistics();
- copyOther.copy(other);
- copyOther.update(fMax);
- copy(copyOther);
- } else {
- internalMerge(other);
- }
+ fStatistics.merge(other.getStatObject());
}
- private void internalMerge(SegmentStoreStatistics other) {
- /*
- * Min and max are trivial, as well as number of segments
- */
- long min = fMin.getLength();
- long max = fMax.getLength();
- fMin = min <= other.getMin() ? fMin : other.getMinSegment();
- fMax = max >= other.getMax() ? fMax : other.getMaxSegment();
-
- long oldNbSeg = fNbSegments;
- double oldAverage = fAverage;
- long otherSegments = other.getNbSegments();
- double otherAverage = other.getAverage();
- fNbSegments += otherSegments;
- fTotal += other.getTotal();
-
- /*
- * Average is a weighted average
- */
- fAverage = ((oldNbSeg * oldAverage) + (otherAverage * otherSegments)) / fNbSegments;
-
- /*
- * This one is a bit tricky.
- *
- * The variance is the sum of the deltas from a mean squared.
- *
- * So if we add the old mean squared back to to variance and remove the
- * new mean, the standard deviation can be easily calculated.
- */
- double avg1Sq = oldAverage * oldAverage;
- double avg2sq = otherAverage * otherAverage;
- double avgtSq = fAverage * fAverage;
- /*
- * This is a tricky part, bear in mind that the set is not continuous but discrete,
- * Therefore, we have for n elements, n-1 intervals between them.
- * Ergo, n-1 intervals are used for divisions and multiplications.
- */
- double variance1 = fVariance / (oldNbSeg - 1);
- double variance2 = other.fVariance / (otherSegments - 1);
- fVariance = ((variance1 + avg1Sq - avgtSq) * (oldNbSeg - 1) + (variance2 + avg2sq - avgtSq) * (otherSegments - 1));
+ private IStatistics<ISegment> getStatObject() {
+ return fStatistics;
}
- private void copy(SegmentStoreStatistics copyOther) {
- fAverage = copyOther.fAverage;
- fMax = copyOther.fMax;
- fMin = copyOther.fMin;
- fNbSegments = copyOther.fNbSegments;
- fTotal = copyOther.fTotal;
- fVariance = copyOther.fVariance;
- }
}
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 1.2.0.qualifier
+Bundle-Version: 1.3.0.qualifier
Bundle-Localization: plugin
Bundle-SymbolicName: org.eclipse.tracecompass.analysis.timing.ui;singleton:=true
Bundle-Activator: org.eclipse.tracecompass.internal.analysis.timing.ui.Activator
* Abstract view to to be extended to display segment store statistics.
*
* @author Bernd Hufmann
- *
+ * @deprecated use {@link AbstractSegmentsStatisticsView} instead
*/
+@Deprecated
public abstract class AbstractSegmentStoreStatisticsView extends TmfView {
private final Action fExportAction = new ExportToTsvAction() {
* statistics
*
* @author Bernd Hufmann
- *
+ * @deprecated use {@link AbstractSegmentsStatisticsViewer} instead
*/
+@Deprecated
public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTreeViewer {
private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 Ericsson, École Polytechnique de Montréal
+ *
+ * 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.tracecompass.analysis.timing.ui.views.segmentstore.statistics;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.ExportToTsvAction;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
+import org.eclipse.tracecompass.tmf.ui.views.TmfView;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+
+/**
+ * Abstract view to to be extended to display segment store statistics.
+ *
+ * @author Bernd Hufmann
+ * @author Geneviève Bastien
+ * @since 1.3
+ */
+public abstract class AbstractSegmentsStatisticsView extends TmfView {
+
+ private final Action fExportAction = new ExportToTsvAction() {
+ @Override
+ protected void exportToTsv(@Nullable OutputStream stream) {
+ AbstractSegmentsStatisticsView.this.exportToTsv(stream);
+ }
+
+ @Override
+ protected @Nullable Shell getShell() {
+ return getViewSite().getShell();
+ }
+
+ };
+
+ private @Nullable AbstractTmfTreeViewer fStatsViewer = null;
+
+ /**
+ * Constructor
+ */
+ public AbstractSegmentsStatisticsView() {
+ super("StatisticsView"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void createPartControl(@Nullable Composite parent) {
+ super.createPartControl(parent);
+ AbstractTmfTreeViewer statsViewer = createSegmentStoreStatisticsViewer(NonNullUtils.checkNotNull(parent));
+ ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
+ if (trace != null) {
+ statsViewer.loadTrace(trace);
+ }
+ fStatsViewer = statsViewer;
+ getViewSite().getActionBars().getMenuManager().add(fExportAction);
+ }
+
+ @Override
+ public void setFocus() {
+ AbstractTmfTreeViewer statsViewer = fStatsViewer;
+ if (statsViewer != null) {
+ statsViewer.getControl().setFocus();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ AbstractTmfTreeViewer statsViewer = fStatsViewer;
+ if (statsViewer != null) {
+ statsViewer.dispose();
+ }
+ }
+
+ /**
+ * Creates a segment store statistics viewer instance.
+ *
+ * @param parent
+ * the parent composite to create the viewer in.
+ * @return the latency statistics viewer implementation
+ */
+ protected abstract AbstractTmfTreeViewer createSegmentStoreStatisticsViewer(Composite parent);
+
+ /**
+ * Export a given items's TSV
+ *
+ * @param stream
+ * an output stream to write the TSV to
+ * @since 1.2
+ */
+ @VisibleForTesting
+ protected void exportToTsv(@Nullable OutputStream stream) {
+ try (PrintWriter pw = new PrintWriter(stream)) {
+ AbstractTmfTreeViewer statsViewer = fStatsViewer;
+ if (statsViewer == null) {
+ return;
+ }
+ Tree tree = statsViewer.getTreeViewer().getTree();
+ int size = tree.getItemCount();
+ List<String> columns = new ArrayList<>();
+ for (int i = 0; i < tree.getColumnCount(); i++) {
+ String valueOf = String.valueOf(tree.getColumn(i).getText());
+ if (valueOf.isEmpty() && i == tree.getColumnCount() - 1) {
+ // Linux "feature", an invisible column is added at the end
+ // with gtk2
+ break;
+ }
+ columns.add(valueOf);
+ }
+ String join = Joiner.on('\t').skipNulls().join(columns);
+ pw.println(join);
+ for (int i = 0; i < size; i++) {
+ TreeItem item = tree.getItem(i);
+ printItem(pw, columns, item);
+ }
+ }
+ }
+
+ private void printItem(PrintWriter pw, List<String> columns, @Nullable TreeItem item) {
+ if (item == null) {
+ return;
+ }
+ List<String> data = new ArrayList<>();
+ for (int col = 0; col < columns.size(); col++) {
+ data.add(String.valueOf(item.getText(col)));
+ }
+ pw.println(Joiner.on('\t').join(data));
+ for (TreeItem child : item.getItems()) {
+ printItem(pw, columns, child);
+ }
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 Ericsson, École Polytechnique de Montréal
+ *
+ * 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.tracecompass.analysis.timing.ui.views.segmentstore.statistics;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.text.Format;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
+import org.eclipse.tracecompass.analysis.timing.core.statistics.Statistics;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics.Messages;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
+
+/**
+ * An abstract tree viewer implementation for displaying segment store
+ * statistics
+ *
+ * @author Bernd Hufmann
+ * @author Geneviève Bastien
+ * @since 1.3
+ */
+public abstract class AbstractSegmentsStatisticsViewer extends AbstractTmfTreeViewer {
+
+ private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
+
+ private @Nullable TmfAbstractAnalysisModule fModule;
+ private MenuManager fTablePopupMenuManager;
+
+ private static final String[] COLUMN_NAMES = new String[] {
+ checkNotNull(Messages.SegmentStoreStatistics_LevelLabel),
+ checkNotNull(Messages.SegmentStoreStatistics_Statistics_MinLabel),
+ checkNotNull(Messages.SegmentStoreStatistics_MaxLabel),
+ checkNotNull(Messages.SegmentStoreStatistics_AverageLabel),
+ checkNotNull(Messages.SegmentStoreStatisticsViewer_StandardDeviation),
+ checkNotNull(Messages.SegmentStoreStatisticsViewer_Count),
+ checkNotNull(Messages.SegmentStoreStatisticsViewer_Total)
+ };
+
+ /**
+ * Constructor
+ *
+ * @param parent
+ * the parent composite
+ */
+ public AbstractSegmentsStatisticsViewer(Composite parent) {
+ super(parent, false);
+ setLabelProvider(new SegmentStoreStatisticsLabelProvider());
+ fTablePopupMenuManager = new MenuManager();
+ fTablePopupMenuManager.setRemoveAllWhenShown(true);
+ fTablePopupMenuManager.addMenuListener(manager -> {
+ TreeViewer viewer = getTreeViewer();
+ ISelection selection = viewer.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection sel = (IStructuredSelection) selection;
+ if (manager != null) {
+ appendToTablePopupMenu(manager, sel);
+ }
+ }
+ });
+ Menu tablePopup = fTablePopupMenuManager.createContextMenu(getTreeViewer().getTree());
+ Tree tree = getTreeViewer().getTree();
+ tree.setMenu(tablePopup);
+ tree.addDisposeListener(e -> {
+ if (fModule != null) {
+ fModule.dispose();
+ }
+ });
+ }
+
+ /** Provides label for the Segment Store tree viewer cells */
+ protected static class SegmentStoreStatisticsLabelProvider extends TreeLabelProvider {
+
+ @Override
+ public String getColumnText(@Nullable Object element, int columnIndex) {
+ String value = ""; //$NON-NLS-1$
+ if (element instanceof HiddenTreeViewerEntry) {
+ if (columnIndex == 0) {
+ value = ((HiddenTreeViewerEntry) element).getName();
+ }
+ } else if (element instanceof SegmentStoreStatisticsEntry) {
+ SegmentStoreStatisticsEntry entry = (SegmentStoreStatisticsEntry) element;
+ if (columnIndex == 0) {
+ return String.valueOf(entry.getName());
+ }
+ if (entry.getEntry().getNbElements() > 0) {
+ if (columnIndex == 1) {
+ value = toFormattedString(entry.getEntry().getMin());
+ } else if (columnIndex == 2) {
+ value = String.valueOf(toFormattedString(entry.getEntry().getMax()));
+ } else if (columnIndex == 3) {
+ value = String.valueOf(toFormattedString(entry.getEntry().getMean()));
+ } else if (columnIndex == 4) {
+ value = String.valueOf(toFormattedString(entry.getEntry().getStdDev()));
+ } else if (columnIndex == 5) {
+ value = String.valueOf(entry.getEntry().getNbElements());
+ } else if (columnIndex == 6) {
+ value = String.valueOf(toFormattedString(entry.getEntry().getTotal()));
+ }
+ }
+ }
+ return checkNotNull(value);
+ }
+ }
+
+ /**
+ * Creates the statistics analysis module
+ *
+ * @return the statistics analysis module
+ */
+ @Nullable
+ protected abstract TmfAbstractAnalysisModule createStatisticsAnalysiModule();
+
+ /**
+ * Gets the statistics analysis module
+ *
+ * @return the statistics analysis module
+ */
+ @Nullable
+ public TmfAbstractAnalysisModule getStatisticsAnalysisModule() {
+ return fModule;
+ }
+
+ @Override
+ protected ITmfTreeColumnDataProvider getColumnDataProvider() {
+ return new ITmfTreeColumnDataProvider() {
+
+ @Override
+ public List<@Nullable TmfTreeColumnData> getColumnData() {
+ /* All columns are sortable */
+ List<@Nullable TmfTreeColumnData> columns = new ArrayList<>();
+ TmfTreeColumnData column = new TmfTreeColumnData(COLUMN_NAMES[0]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return n1.getName().compareTo(n2.getName());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[1]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return Long.compare(n1.getEntry().getMin(), n2.getEntry().getMin());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[2]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return Long.compare(n1.getEntry().getMax(), n2.getEntry().getMax());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[3]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return Double.compare(n1.getEntry().getMean(), n2.getEntry().getMean());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[4]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return Double.compare(n1.getEntry().getStdDev(), n2.getEntry().getStdDev());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[5]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return Long.compare(n1.getEntry().getNbElements(), n2.getEntry().getNbElements());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[6]);
+ column.setAlignment(SWT.RIGHT);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+ if ((e1 == null) || (e2 == null)) {
+ return 0;
+ }
+
+ SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+ SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+ return Double.compare(n1.getEntry().getTotal(), n2.getEntry().getTotal());
+
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(""); //$NON-NLS-1$
+ columns.add(column);
+ return columns;
+ }
+
+ };
+ }
+
+ @Override
+ public void initializeDataSource() {
+ ITmfTrace trace = getTrace();
+ if (trace != null) {
+ TmfAbstractAnalysisModule module = createStatisticsAnalysiModule();
+ if (module == null) {
+ return;
+ }
+ try {
+ module.setTrace(trace);
+ module.schedule();
+ if (fModule != null) {
+ fModule.dispose();
+ }
+ fModule = module;
+ } catch (TmfAnalysisException e) {
+ Activator.getDefault().logError("Error initializing statistics analysis module", e); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Method to add commands to the context sensitive menu.
+ *
+ * @param manager
+ * the menu manager
+ * @param sel
+ * the current selection
+ */
+ protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
+ Object element = sel.getFirstElement();
+ if ((element instanceof SegmentStoreStatisticsEntry) && !(element instanceof HiddenTreeViewerEntry)) {
+ final SegmentStoreStatisticsEntry segment = (SegmentStoreStatisticsEntry) element;
+ IAction gotoStartTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMinAction) {
+ @Override
+ public void run() {
+ ISegment minObject = segment.getEntry().getMinObject();
+ long start = minObject == null ? 0 : minObject.getStart();
+ long end = minObject == null ? 0 : minObject.getEnd();
+ broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentsStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
+ updateContent(start, end, true);
+ }
+ };
+
+ IAction gotoEndTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMaxAction) {
+ @Override
+ public void run() {
+ ISegment maxObject = segment.getEntry().getMaxObject();
+ long start = maxObject == null ? 0 : maxObject.getStart();
+ long end = maxObject == null ? 0 : maxObject.getEnd();
+ broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentsStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
+ updateContent(start, end, true);
+ }
+ };
+
+ manager.add(gotoStartTime);
+ manager.add(gotoEndTime);
+ }
+ }
+
+ /**
+ * Formats a double value string
+ *
+ * @param value
+ * a value to format
+ * @return formatted value
+ */
+ protected static String toFormattedString(double value) {
+ // The cast to long is needed because the formatter cannot truncate the
+ // number.
+ String percentageString = String.format("%s", FORMATTER.format(value)); //$NON-NLS-1$
+ return percentageString;
+ }
+
+ /**
+ * Class for defining an entry in the statistics tree.
+ */
+ protected class SegmentStoreStatisticsEntry extends TmfTreeViewerEntry {
+
+ private final IStatistics<ISegment> fEntry;
+
+ /**
+ * Constructor
+ *
+ * @param name
+ * name of entry
+ *
+ * @param entry
+ * segment store statistics object
+ */
+ public SegmentStoreStatisticsEntry(String name, IStatistics<ISegment> entry) {
+ super(name);
+ fEntry = entry;
+ }
+
+ /**
+ * Gets the statistics object
+ *
+ * @return statistics object
+ */
+ public IStatistics<ISegment> getEntry() {
+ return fEntry;
+ }
+
+ }
+
+ @Override
+ protected @Nullable ITmfTreeViewerEntry updateElements(long start, long end, boolean isSelection) {
+
+ TmfAbstractAnalysisModule analysisModule = getStatisticsAnalysisModule();
+
+ if (getTrace() == null || !(analysisModule instanceof AbstractSegmentStatisticsAnalysis)) {
+ return null;
+ }
+
+ AbstractSegmentStatisticsAnalysis module = (AbstractSegmentStatisticsAnalysis) analysisModule;
+
+ module.waitForCompletion();
+
+ TmfTreeViewerEntry root = new TmfTreeViewerEntry(""); //$NON-NLS-1$
+ List<ITmfTreeViewerEntry> entryList = root.getChildren();
+
+ if (isSelection) {
+ setStats(start, end, entryList, module, true, new NullProgressMonitor());
+ }
+ setStats(start, end, entryList, module, false, new NullProgressMonitor());
+ return root;
+ }
+
+ private void setStats(long start, long end, List<ITmfTreeViewerEntry> entryList, AbstractSegmentStatisticsAnalysis module, boolean isSelection, IProgressMonitor monitor) {
+ String label = isSelection ? getSelectionLabel() : getTotalLabel();
+ final IStatistics<ISegment> entry = isSelection ? module.getStatsForRange(start, end, monitor) : module.getStatsTotal();
+ if (entry != null) {
+
+ if (entry.getNbElements() == 0) {
+ return;
+ }
+ TmfTreeViewerEntry child = new SegmentStoreStatisticsEntry(checkNotNull(label), entry);
+ entryList.add(child);
+
+ final Map<@NonNull String, IStatistics<ISegment>> perTypeStats = isSelection ? module.getStatsPerTypeForRange(start, end, monitor) : module.getStatsPerType();
+ for (Entry<@NonNull String, IStatistics<ISegment>> statsEntry : perTypeStats.entrySet()) {
+ child.addChild(new SegmentStoreStatisticsEntry(statsEntry.getKey(), statsEntry.getValue()));
+ }
+ }
+ }
+
+ @Override
+ @TmfSignalHandler
+ public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) {
+ // Do nothing. We do not want to update the view and lose the selection
+ // if the window range is updated with current selection outside of this
+ // new range.
+ }
+
+ /**
+ * Get the type label
+ *
+ * @return the label
+ * @since 1.2
+ */
+ protected String getTypeLabel() {
+ return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_types);
+ }
+
+ /**
+ * Get the total column label
+ *
+ * @return the totals column label
+ * @since 1.2
+ */
+ protected String getTotalLabel() {
+ return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_total);
+ }
+
+ /**
+ * Get the selection column label
+ *
+ * @return The selection column label
+ * @since 1.2
+ */
+ protected String getSelectionLabel() {
+ return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_selection);
+ }
+
+ /**
+ * Class to define a level in the tree that doesn't have any values.
+ */
+ protected class HiddenTreeViewerEntry extends SegmentStoreStatisticsEntry {
+ /**
+ * Constructor
+ *
+ * @param name
+ * the name of the level
+ */
+ public HiddenTreeViewerEntry(String name) {
+ super(name, new Statistics<>(s -> s.getLength()));
+ }
+ }
+
+}
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsView;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.TmfXmlUiStrings;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.ui.views.XmlLatencyViewInfo;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
/**
* The statistic view for pattern latency analysis
*
* @author Jean-Christian Kouame
*/
-public class PatternStatisticsView extends AbstractSegmentStoreStatisticsView {
+public class PatternStatisticsView extends AbstractSegmentsStatisticsView {
private PatternStatisticsViewer fViewer;
/** The view's ID */
}
@Override
- protected @NonNull AbstractSegmentStoreStatisticsViewer createSegmentStoreStatisticsViewer(@NonNull Composite parent) {
+ protected @NonNull AbstractTmfTreeViewer createSegmentStoreStatisticsViewer(@NonNull Composite parent) {
PatternStatisticsViewer viewer = new PatternStatisticsViewer(parent);
fViewer = viewer;
loadStatisticView();
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.swt.widgets.Composite;
-import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsViewer;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentsStatisticsViewer;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternLatencyStatisticsAnalysis;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
*
* @author Jean-Christian Kouame
*/
-public class PatternStatisticsViewer extends AbstractSegmentStoreStatisticsViewer {
+public class PatternStatisticsViewer extends AbstractSegmentsStatisticsViewer {
private String fAnalysisId;