From 55905e73c218ab65329b25467590aa4103ad373b Mon Sep 17 00:00:00 2001 From: Puru Jaiswal Date: Mon, 11 Jul 2022 09:35:43 -0500 Subject: [PATCH] timing.core: add Segment Store Density Provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently for the function density views there is no data provider for it and the logic for data and UI are in the same file, to improve the efficiency a data provider is created for function density views. [Added] SegmentStoreDensityDataProvider{Factory} for density views. Change-Id: I3b6521b5e9aab90669f61315e804f9e326807a5b Signed-off-by: Puru Jaiswal  Reviewed-on: https://git.eclipse.org/r/c/tracecompass/org.eclipse.tracecompass/+/194660 Tested-by: Marco Miller Reviewed-by: Marco Miller --- .../SegmentStoreDensityDataProviderTest.java | 174 ++++++++++++++++++ .../StubSegmentStoreProvider.java | 23 +++ .../plugin.xml | 4 + .../timing/core/segmentstore/Messages.java | 10 + .../SegmentStoreDensityDataProvider.java | 163 ++++++++++++++++ ...egmentStoreDensityDataProviderFactory.java | 49 +++++ .../core/segmentstore/messages.properties | 3 + .../DataProviderManagerTest.java | 24 +++ 8 files changed, 450 insertions(+) create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/SegmentStoreDensityDataProviderTest.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProvider.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProviderFactory.java diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/SegmentStoreDensityDataProviderTest.java b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/SegmentStoreDensityDataProviderTest.java new file mode 100644 index 0000000000..28778ce768 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/SegmentStoreDensityDataProviderTest.java @@ -0,0 +1,174 @@ +/********************************************************************** + * Copyright (c) 2022 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ +package org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProvider; +import org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProviderFactory; +import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.tracecompass.tmf.core.model.SeriesModel; +import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter; +import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeDataModel; +import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel; +import org.eclipse.tracecompass.tmf.core.model.xy.ITmfTreeXYDataProvider; +import org.eclipse.tracecompass.tmf.core.model.xy.ITmfXyModel; +import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub; +import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStubNs; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Tests the {@Link SegmentStoreDensityDataProvider} + * + * @author Puru Jaiswal + */ +public class SegmentStoreDensityDataProviderTest { + + private static ITmfTreeXYDataProvider<@NonNull TmfTreeDataModel> fDataProvider; + private static ITmfTreeXYDataProvider<@NonNull TmfTreeDataModel> fDataProviderNullSegments; + + @NonNull + private static final TmfXmlTraceStub fTrace = new TmfXmlTraceStubNs(); + private static final double[] yValues = new double[] { 15.0, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 15.0, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 15.0, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 15.0, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 15.0, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 15.0, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 15.0, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324 }; + private static final long[] xValues = new long[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5 }; + private static final long[] xValuesNull = new long[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 }; + private static final double[] yValuesNull = new double[] { 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, + 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324, 4.9E-324 }; + private static final String ID = "org.eclipse.tracecompass.analysis.timing.core.tests.segmentstore"; + + /** + * Set-up resources + * + * @throws TmfAnalysisException + * Trace exception should not happen + */ + @BeforeClass + public static void init() throws TmfAnalysisException { + StubSegmentStoreProvider fixture = getValidSegment(fTrace); + IDataProviderFactory fp = new SegmentStoreDensityDataProviderFactory(); + assertNull(fp.createProvider(fTrace)); + assertNotNull(fp.createProvider(fTrace, ID)); + assertTrue(fp.getDescriptors(fTrace).isEmpty()); + fDataProvider = new SegmentStoreDensityDataProvider(fTrace, fixture, ID); + StubSegmentStoreProvider fixtureNull = getValidNullSegment(fTrace); + IDataProviderFactory fpNullSegment = new SegmentStoreDensityDataProviderFactory(); + assertNull(fpNullSegment.createProvider(fTrace)); + assertNotNull(fpNullSegment.createProvider(fTrace, ID)); + assertTrue(fpNullSegment.getDescriptors(fTrace).isEmpty()); + fDataProviderNullSegments = new SegmentStoreDensityDataProvider(fTrace, fixtureNull, ID); + } + + /** + * Disposing resources + */ + @AfterClass + public static void clean() { + fTrace.dispose(); + } + + private static @NonNull StubSegmentStoreProvider getValidSegment(@NonNull ITmfTrace trace) throws TmfAnalysisException { + StubSegmentStoreProvider fixture = new StubSegmentStoreProvider(false); + fixture.setTrace(trace); + fixture.schedule(); + fixture.waitForCompletion(); + return fixture; + } + + private static @NonNull StubSegmentStoreProvider getValidNullSegment(@NonNull ITmfTrace trace) throws TmfAnalysisException { + StubSegmentStoreProvider fixture = new StubSegmentStoreProvider(true); + fixture.setTrace(trace); + fixture.schedule(); + fixture.waitForCompletion(); + return fixture; + } + + /** + * Tests data model returned by the fetch XY + */ + @Test() + public void testDataProviderFetchXY() { + TimeQueryFilter timeQueryFilter = new TimeQueryFilter(0, 100, 100); + TmfModelResponse<@NonNull ITmfXyModel> response = fDataProvider.fetchXY(FetchParametersUtils.timeQueryToMap(timeQueryFilter), null); + assertNotNull(response); + ITmfXyModel responseModel = response.getModel(); + assertNotNull(responseModel); + SeriesModel seriesResponse = (SeriesModel) responseModel.getSeriesData().toArray()[0]; + assertTrue(Arrays.equals(yValues, seriesResponse.getData())); + assertTrue(Arrays.equals(xValues, seriesResponse.getXAxis())); + } + + /** + * Tests data model returned by the fetch XY + */ + @Test() + public void testDataProviderNullFetchXY() { + TimeQueryFilter timeQueryFilter = new TimeQueryFilter(0, 100, 100); + TmfModelResponse<@NonNull ITmfXyModel> response = fDataProviderNullSegments.fetchXY(FetchParametersUtils.timeQueryToMap(timeQueryFilter), null); + assertNotNull(response); + ITmfXyModel responseModel = response.getModel(); + assertNotNull(responseModel); + SeriesModel seriesResponse = (SeriesModel) responseModel.getSeriesData().toArray()[0]; + assertTrue(Arrays.equals(yValuesNull, seriesResponse.getData())); + assertTrue(Arrays.equals(xValuesNull, seriesResponse.getXAxis())); + } + + /** + * Tests fetch tree of the data provider + */ + @Test() + public void testFetchTree() { + TimeQueryFilter timeQueryFilter = new TimeQueryFilter(0, 100, 100); + TmfModelResponse<@NonNull TmfTreeModel<@NonNull TmfTreeDataModel>> response = fDataProvider.fetchTree(FetchParametersUtils.timeQueryToMap(timeQueryFilter), null); + assertNotNull(response); + } + + /** + * Tests provider ID + */ + @Test + public void testID() { + assertTrue(fDataProvider.getId().equals(ID)); + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/StubSegmentStoreProvider.java b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/StubSegmentStoreProvider.java index 7b9ed0263a..e93ba51ae7 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/StubSegmentStoreProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core.tests/src/org/eclipse/tracecompass/analysis/timing/core/tests/segmentstore/StubSegmentStoreProvider.java @@ -88,6 +88,29 @@ public StubSegmentStoreProvider() { fPreFixture = builder.build(); } + /** + * Constructor to initialize segments + * + * @param nullSegments + * : to decide on null or not null segments + */ + public StubSegmentStoreProvider(boolean nullSegments) { + ImmutableList.Builder<@NonNull ISegment> builder = new Builder<>(); + if (nullSegments) { + fPreFixture = builder.build(); + } else { + int previousStartTime = 0; + for (int i = 0; i < SIZE; i++) { + if (i % 7 == 0) { + previousStartTime = i; + } + ISegment segment = new BasicSegment(previousStartTime, i); + builder.add(segment); + } + fPreFixture = builder.build(); + } + } + @Override protected boolean buildAnalysisSegments(@NonNull ISegmentStore<@NonNull ISegment> segmentStore, @NonNull IProgressMonitor monitor) throws TmfAnalysisException { return segmentStore.addAll(fPreFixture); diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/plugin.xml b/analysis/org.eclipse.tracecompass.analysis.timing.core/plugin.xml index b093caabf2..3fc1a71d62 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/plugin.xml +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/plugin.xml @@ -30,5 +30,9 @@ class="org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreTableDataProviderFactory" id="org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreTableDataProvider"> + + diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/Messages.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/Messages.java index a600db0af2..0612340967 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/Messages.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/Messages.java @@ -139,6 +139,16 @@ public class Messages extends NLS { */ public static @Nullable String SegmentStoreTableDataProvider_description; + /** + * Segment store density title + */ + public static @Nullable String SegmentStoreDensityDataProvider_title; + + /** + * Segment store density total + */ + public static @Nullable String SegmentStoreDensity_TotalLabel; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProvider.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProvider.java new file mode 100644 index 0000000000..0702060721 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProvider.java @@ -0,0 +1,163 @@ +/********************************************************************** + * Copyright (c) 2022 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.StreamSupport; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider; +import org.eclipse.tracecompass.internal.tmf.core.model.TmfXyResponseFactory; +import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils; +import org.eclipse.tracecompass.segmentstore.core.ISegment; +import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; +import org.eclipse.tracecompass.segmentstore.core.SegmentComparators; +import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; +import org.eclipse.tracecompass.tmf.core.model.AbstractTmfTraceDataProvider; +import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage; +import org.eclipse.tracecompass.tmf.core.model.YModel; +import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter; +import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeDataModel; +import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel; +import org.eclipse.tracecompass.tmf.core.model.xy.ITmfTreeXYDataProvider; +import org.eclipse.tracecompass.tmf.core.model.xy.ITmfXyModel; +import org.eclipse.tracecompass.tmf.core.model.xy.IYModel; +import org.eclipse.tracecompass.tmf.core.response.ITmfResponse; +import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; + +/** + * This data provider will return an XY model based on a query filter. The model + * can be used by any viewer to draw density view charts. Model returned is for + * analysis using SegmentStore. + * + * @author Puru Jaiswal + */ +public class SegmentStoreDensityDataProvider extends AbstractTmfTraceDataProvider implements ITmfTreeXYDataProvider { + + /** + * Extension point ID. + */ + public static final String ID = "org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProvider"; //$NON-NLS-1$ + private static final AtomicLong TRACE_IDS = new AtomicLong(); + + private final String fID; + private final String title = Objects.requireNonNull(Messages.SegmentStoreDensityDataProvider_title); + private final ISegmentStoreProvider fProvider; + private final long fTotalId = TRACE_IDS.getAndIncrement(); + private final long fTraceId = TRACE_IDS.getAndIncrement(); + + /** + * Constructor + * + * @param trace + * trace provider with other properties of trace. + * @param provider + * segment store provider + * @param id + * analysis identifier + */ + public SegmentStoreDensityDataProvider(ITmfTrace trace, ISegmentStoreProvider provider, String id) { + super(trace); + fProvider = provider; + fID = id; + if (provider instanceof IAnalysisModule) { + ((IAnalysisModule) provider).waitForCompletion(); + } + } + + @Override + public TmfModelResponse fetchXY(Map fetchParameters, @Nullable IProgressMonitor monitor) { + ISegmentStore segmentStore = fProvider.getSegmentStore(); + if (segmentStore == null) { + return TmfXyResponseFactory.createFailedResponse(Objects.requireNonNull(Messages.SegmentStoreDataProvider_SegmentNotAvailable)); + } + TimeQueryFilter queryFilter = FetchParametersUtils.createSelectionTimeQuery(fetchParameters); + if (queryFilter == null) { + queryFilter = FetchParametersUtils.createTimeQuery(fetchParameters); + if (queryFilter == null) { + return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.INCORRECT_QUERY_PARAMETERS); + } + } + return getXyData(segmentStore, queryFilter); + } + + private TmfModelResponse getXyData(ISegmentStore segmentStore, TimeQueryFilter queryFilter) { + long startTraceTime = queryFilter.getStart(); + long endTraceTime = queryFilter.getEnd(); + int width = queryFilter.getTimesRequested().length; + Iterable displayData = segmentStore.getIntersectingElements(startTraceTime, endTraceTime); + + IAnalysisModule module = (fProvider instanceof IAnalysisModule) ? (IAnalysisModule) fProvider : null; + boolean complete = module != null && module.isQueryable(queryFilter.getEnd()); + + Optional maxSegment = StreamSupport.stream(displayData.spliterator(), false).max(SegmentComparators.INTERVAL_LENGTH_COMPARATOR); + long maxLength = 1; + if (maxSegment.isPresent()) { + maxLength = maxSegment.get().getLength(); + } + + double[] yValues = getYValues(displayData, width, maxLength); + long[] xValues = getXValues(width, maxLength); + ImmutableList.Builder builder = ImmutableList.builder(); + String totalName = getTrace().getName() + '/' + Messages.SegmentStoreDensity_TotalLabel; + builder.add(new YModel(fTotalId, totalName, yValues)); + return TmfXyResponseFactory.create(title, xValues, builder.build(), complete); + } + + private static long[] getXValues(int width, long maxLength) { + double timeWidth = (double) maxLength / (double) width; + long[] xValues = new long[width]; + for (int i = 0; i < width; i++) { + xValues[i] = (long) (i * timeWidth); + xValues[i] += timeWidth / 2; + } + return xValues; + } + + private static double[] getYValues(Iterable displayData, int width, long maxLength) { + double maxFactor = 1.0 / (maxLength + 1.0); + double[] yValues = new double[width]; + Arrays.fill(yValues, Double.MIN_VALUE); + for (ISegment segment : displayData) { + double xBox = segment.getLength() * maxFactor * width; + if (yValues[(int) xBox] < 1) { + yValues[(int) xBox] = 1; + } else { + yValues[(int) xBox]++; + } + } + return yValues; + } + + @Override + public TmfModelResponse> fetchTree(Map fetchParameters, @Nullable IProgressMonitor monitor) { + Builder builder = ImmutableList.builder(); + builder.add(new TmfTreeDataModel(fTraceId, -1, Collections.singletonList(String.valueOf(getTrace().getName())))); + builder.add(new TmfTreeDataModel(fTotalId, fTraceId, Collections.singletonList(Objects.requireNonNull(Messages.SegmentStoreDensity_TotalLabel)))); + return new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), builder.build()), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); + } + + @Override + public String getId() { + return fID; + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProviderFactory.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProviderFactory.java new file mode 100644 index 0000000000..61290fa344 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/SegmentStoreDensityDataProviderFactory.java @@ -0,0 +1,49 @@ +/********************************************************************** + * Copyright (c) 2022 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License 2.0 which + * accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ +package org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreAnalysisModule; +import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; +import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataModel; +import org.eclipse.tracecompass.tmf.core.model.tree.ITmfTreeDataProvider; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +/** + * Generalized {@link SegmentStoreDensityDataProvider} factory using secondary + * ID to identify which segment store provider to build it from. + * + * @author Puru Jaiswal + */ +public class SegmentStoreDensityDataProviderFactory implements IDataProviderFactory { + + @Override + public @Nullable ITmfTreeDataProvider createProvider(ITmfTrace trace) { + return null; + } + + @Override + public @Nullable ITmfTreeDataProvider createProvider(ITmfTrace trace, String secondaryId) { + IAnalysisModule m = new SegmentStoreAnalysisModule(trace, secondaryId); + try { + m.setTrace(trace); + String composedId = SegmentStoreDensityDataProvider.ID + ":" + secondaryId; //$NON-NLS-1$ + m.schedule(); + return new SegmentStoreDensityDataProvider(trace, (ISegmentStoreProvider) m, composedId); + } catch (TmfAnalysisException ex) { + m.dispose(); + return null; + } + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/messages.properties b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/messages.properties index e152a9d982..a6fb225378 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/messages.properties +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/segmentstore/messages.properties @@ -28,6 +28,9 @@ SegmentStoreTableDataProvider_description=Show latency table provided by {0} SegmentStoreScatterGraphDataProvider_title={0} - Latency vs Time SegmentStoreScatterGraphDataProvider_description=Show latencies provided by {0} +SegmentStoreDensityDataProvider_title={0} - Function Density + +SegmentStoreDensity_TotalLabel=Total SegmentStoreStatistics_Label=Label SegmentStoreStatistics_MinLabel=Minimum SegmentStoreStatistics_MaxLabel=Maximum diff --git a/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java b/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java index 07dd477609..5a7a6f7d6e 100644 --- a/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java +++ b/releng/org.eclipse.tracecompass.integration.core.tests/src/org/eclipse/tracecompass/integration/core/tests/dataproviders/DataProviderManagerTest.java @@ -86,6 +86,12 @@ public class DataProviderManagerTest { .setId("org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreTableDataProvider:lttng.analysis.futex"); EXPECTED_KERNEL_DP_DESCRIPTORS.add(builder.build()); builder = new DataProviderDescriptor.Builder(); + builder.setName("Futex Contention Analysis - Function Density") + .setDescription("Show function density provided by Analysis module: Futex Contention Analysis") + .setProviderType(ProviderType.TREE_TIME_XY) + .setId("org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProvider:lttng.analysis.futex"); + EXPECTED_KERNEL_DP_DESCRIPTORS.add(builder.build()); + builder = new DataProviderDescriptor.Builder(); builder.setName("Futex Contention Analysis - Latency vs Time") .setDescription("Show latencies provided by Analysis module: Futex Contention Analysis") .setProviderType(ProviderType.TREE_TIME_XY) @@ -110,6 +116,12 @@ public class DataProviderManagerTest { .setId("org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreTableDataProvider:lttng.analysis.irq"); EXPECTED_KERNEL_DP_DESCRIPTORS.add(builder.build()); builder = new DataProviderDescriptor.Builder(); + builder.setName("IRQ Analysis - Function Density") + .setDescription("Show function density provided by Analysis module: IRQ Analysis") + .setProviderType(ProviderType.TREE_TIME_XY) + .setId("org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProvider:lttng.analysis.irq"); + EXPECTED_KERNEL_DP_DESCRIPTORS.add(builder.build()); + builder = new DataProviderDescriptor.Builder(); builder.setName("IRQ Analysis - Latency vs Time") .setDescription("Show latencies provided by Analysis module: IRQ Analysis") .setProviderType(ProviderType.TREE_TIME_XY) @@ -140,6 +152,12 @@ public class DataProviderManagerTest { .setId("org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreTableDataProvider:org.eclipse.tracecompass.analysis.os.linux.latency.syscall"); EXPECTED_KERNEL_DP_DESCRIPTORS.add(builder.build()); builder = new DataProviderDescriptor.Builder(); + builder.setName("System Call Latency - Function Density") + .setDescription("Show function density provided by Analysis module: System Call Latency") + .setProviderType(ProviderType.TREE_TIME_XY) + .setId("org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProvider:org.eclipse.tracecompass.analysis.os.linux.latency.syscall"); + EXPECTED_KERNEL_DP_DESCRIPTORS.add(builder.build()); + builder = new DataProviderDescriptor.Builder(); builder.setName("System Call Latency - Latency vs Time") .setDescription("Show latencies provided by Analysis module: System Call Latency") .setProviderType(ProviderType.TREE_TIME_XY) @@ -190,6 +208,12 @@ public class DataProviderManagerTest { .setId("org.eclipse.tracecompass.analysis.timing.core.segmentstore.SegmentStoreTableDataProvider:org.eclipse.linuxtools.lttng2.ust.analysis.callstack"); EXPECTED_UST_DP_DESCRIPTORS.add(builder.build()); builder = new DataProviderDescriptor.Builder(); + builder.setName("LTTng-UST CallStack - Function Density") + .setDescription("Show function density provided by Analysis module: LTTng-UST CallStack") + .setProviderType(ProviderType.TREE_TIME_XY) + .setId("org.eclipse.tracecompass.internal.analysis.timing.core.segmentstore.SegmentStoreDensityDataProvider:org.eclipse.linuxtools.lttng2.ust.analysis.callstack"); + EXPECTED_UST_DP_DESCRIPTORS.add(builder.build()); + builder = new DataProviderDescriptor.Builder(); builder.setName("LTTng-UST CallStack - Latency vs Time") .setDescription("Show latencies provided by Analysis module: LTTng-UST CallStack") .setProviderType(ProviderType.TREE_TIME_XY)