diff --git a/features/nl.esi.pps.tmsc.cpu.ui.feature/.project b/features/nl.esi.pps.tmsc.cpu.ui.feature/.project new file mode 100644 index 0000000..3dd511b --- /dev/null +++ b/features/nl.esi.pps.tmsc.cpu.ui.feature/.project @@ -0,0 +1,17 @@ + + + nl.esi.pps.tmsc.cpu.ui.feature + + + + + + org.eclipse.pde.FeatureBuilder + + + + + + org.eclipse.pde.FeatureNature + + diff --git a/features/nl.esi.pps.tmsc.cpu.ui.feature/.settings/org.eclipse.core.resources.prefs b/features/nl.esi.pps.tmsc.cpu.ui.feature/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/features/nl.esi.pps.tmsc.cpu.ui.feature/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/features/nl.esi.pps.tmsc.cpu.ui.feature/build.properties b/features/nl.esi.pps.tmsc.cpu.ui.feature/build.properties new file mode 100644 index 0000000..09b9d21 --- /dev/null +++ b/features/nl.esi.pps.tmsc.cpu.ui.feature/build.properties @@ -0,0 +1,11 @@ +# +# Copyright (c) 2018-2025 TNO and Contributors to the GitHub community +# +# This program and the accompanying materials are made available +# under the terms of the MIT License which is available at +# https://opensource.org/licenses/MIT +# +# SPDX-License-Identifier: MIT +# + +bin.includes = feature.xml diff --git a/features/nl.esi.pps.tmsc.cpu.ui.feature/feature.xml b/features/nl.esi.pps.tmsc.cpu.ui.feature/feature.xml new file mode 100644 index 0000000..2a3fa08 --- /dev/null +++ b/features/nl.esi.pps.tmsc.cpu.ui.feature/feature.xml @@ -0,0 +1,49 @@ + + + + + + [Enter Feature Description here.] + + + + [Enter Copyright Description here.] + + + + [Enter License Description here.] + + + + + + + + + + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/.classpath b/plugins/nl.esi.pps.tmsc.cpu.edit/.classpath new file mode 100644 index 0000000..2b8bad5 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/.project b/plugins/nl.esi.pps.tmsc.cpu.edit/.project new file mode 100644 index 0000000..ed22f7b --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/.project @@ -0,0 +1,34 @@ + + + nl.esi.pps.tmsc.cpu.edit + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/.settings/org.eclipse.core.resources.prefs b/plugins/nl.esi.pps.tmsc.cpu.edit/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/.settings/org.eclipse.jdt.core.prefs b/plugins/nl.esi.pps.tmsc.cpu.edit/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..23fa13b --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/META-INF/MANIFEST.MF b/plugins/nl.esi.pps.tmsc.cpu.edit/META-INF/MANIFEST.MF new file mode 100644 index 0000000..1be8648 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: TMSC CPU Edit +Bundle-SymbolicName: nl.esi.pps.tmsc.cpu.edit;singleton:=true +Bundle-Version: 0.30.0.qualifier +Require-Bundle: nl.esi.pps.tmsc.edit, + nl.esi.pps.tmsc.cpu +Bundle-Vendor: ESI (TNO) +Automatic-Module-Name: nl.esi.pps.tmsc.cpu.edit +Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/build.properties b/plugins/nl.esi.pps.tmsc.cpu.edit/build.properties new file mode 100644 index 0000000..f1e823f --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/build.properties @@ -0,0 +1,16 @@ +# +# Copyright (c) 2018-2025 TNO and Contributors to the GitHub community +# +# This program and the accompanying materials are made available +# under the terms of the MIT License which is available at +# https://opensource.org/licenses/MIT +# +# SPDX-License-Identifier: MIT +# + +source.. = src/,\ + xtend-gen/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/plugin.xml b/plugins/nl.esi.pps.tmsc.cpu.edit/plugin.xml new file mode 100644 index 0000000..172e296 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/plugin.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/src/nl/esi/pps/tmsc/cpu/edit/ExecutionDataAnalysisItemContentProvider.xtend b/plugins/nl.esi.pps.tmsc.cpu.edit/src/nl/esi/pps/tmsc/cpu/edit/ExecutionDataAnalysisItemContentProvider.xtend new file mode 100644 index 0000000..c6dfdd9 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/src/nl/esi/pps/tmsc/cpu/edit/ExecutionDataAnalysisItemContentProvider.xtend @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu.edit + +import java.util.Collections +import nl.esi.pps.tmsc.Execution +import nl.esi.pps.tmsc.cpu.TmscCpuInfoQueries +import nl.esi.pps.tmsc.provider.dataanalysis.IDataAnalysisItemContentProvider +import nl.esi.pps.tmsc.util.TmscQueries + +import static extension nl.esi.pps.tmsc.cpu.TmscCpuInfoQueries.* + +class ExecutionDataAnalysisItemContentProvider implements IDataAnalysisItemContentProvider { + /** + * Data analysis of On-CPU for all {@link Execution executions} with the same + * {@link Execution#getFunction() function} on the same{@link Execution#getLifeline() executor.} + */ + static final String CONF_ON_CPU = "On-CPU (On same executor)" + + /** + * Data analysis of Wait-for-CPU for all {@link Execution executions} with the same + * {@link Execution#getFunction() function} on the same{@link Execution#getLifeline() executor.} + */ + static final String CONF_WAIT_CPU = "Wait-for-CPU (On same executor)" + + override getConfigurations(Object object) { + val Execution execution = object as Execution + return execution.hasCpuInfo ? newLinkedHashSet(CONF_ON_CPU, CONF_WAIT_CPU) : Collections.emptySet() + } + + override getTitle(Object object, String configuration) { + val Execution execution = object as Execution + return switch (configuration) { + case CONF_ON_CPU: '''On-CPU for «execution.function.name» on «execution.lifeline.executor.name»''' + case CONF_WAIT_CPU: '''Wait-for-CPU for «execution.function.name» on «execution.lifeline.executor.name»''' + default: '''Unsupported configuration: «configuration»''' + } + } + + override getSiblings(Object object, String configuration) { + val Execution execution = object as Execution + return TmscQueries::findAllWithFunctionAndLifeline(execution) + } + + override getDuration(Object object, Object sibling, String configuration) { + val Execution execution = sibling as Execution + return switch (configuration) { + case CONF_ON_CPU: TmscCpuInfoQueries::getOnCpuNanos(execution, true) + case CONF_WAIT_CPU: TmscCpuInfoQueries::getWaitCpuNanos(execution, true) + default: throw new IllegalArgumentException('''Unsupported configuration: «configuration»''') + } + } +} \ No newline at end of file diff --git a/plugins/nl.esi.pps.tmsc.cpu.edit/xtend-gen/nl/esi/pps/tmsc/cpu/edit/ExecutionDataAnalysisItemContentProvider.java b/plugins/nl.esi.pps.tmsc.cpu.edit/xtend-gen/nl/esi/pps/tmsc/cpu/edit/ExecutionDataAnalysisItemContentProvider.java new file mode 100644 index 0000000..9f859d1 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.edit/xtend-gen/nl/esi/pps/tmsc/cpu/edit/ExecutionDataAnalysisItemContentProvider.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu.edit; + +import java.util.Collections; +import java.util.Set; +import nl.esi.pps.tmsc.Execution; +import nl.esi.pps.tmsc.cpu.TmscCpuInfoQueries; +import nl.esi.pps.tmsc.provider.dataanalysis.IDataAnalysisItemContentProvider; +import nl.esi.pps.tmsc.util.TmscQueries; +import org.eclipse.xtend2.lib.StringConcatenation; +import org.eclipse.xtext.xbase.lib.CollectionLiterals; + +@SuppressWarnings("all") +public class ExecutionDataAnalysisItemContentProvider implements IDataAnalysisItemContentProvider { + /** + * Data analysis of On-CPU for all {@link Execution executions} with the same + * {@link Execution#getFunction() function} on the same{@link Execution#getLifeline() executor.} + */ + private static final String CONF_ON_CPU = "On-CPU (On same executor)"; + + /** + * Data analysis of Wait-for-CPU for all {@link Execution executions} with the same + * {@link Execution#getFunction() function} on the same{@link Execution#getLifeline() executor.} + */ + private static final String CONF_WAIT_CPU = "Wait-for-CPU (On same executor)"; + + @Override + public Set getConfigurations(final Object object) { + final Execution execution = ((Execution) object); + Set _xifexpression = null; + boolean _hasCpuInfo = TmscCpuInfoQueries.hasCpuInfo(execution); + if (_hasCpuInfo) { + _xifexpression = CollectionLiterals.newLinkedHashSet(ExecutionDataAnalysisItemContentProvider.CONF_ON_CPU, ExecutionDataAnalysisItemContentProvider.CONF_WAIT_CPU); + } else { + _xifexpression = Collections.emptySet(); + } + return _xifexpression; + } + + @Override + public String getTitle(final Object object, final String configuration) { + final Execution execution = ((Execution) object); + String _switchResult = null; + if (configuration != null) { + switch (configuration) { + case ExecutionDataAnalysisItemContentProvider.CONF_ON_CPU: + StringConcatenation _builder = new StringConcatenation(); + _builder.append("On-CPU for "); + String _name = execution.getFunction().getName(); + _builder.append(_name); + _builder.append(" on "); + String _name_1 = execution.getLifeline().getExecutor().getName(); + _builder.append(_name_1); + _switchResult = _builder.toString(); + break; + case ExecutionDataAnalysisItemContentProvider.CONF_WAIT_CPU: + StringConcatenation _builder_1 = new StringConcatenation(); + _builder_1.append("Wait-for-CPU for "); + String _name_2 = execution.getFunction().getName(); + _builder_1.append(_name_2); + _builder_1.append(" on "); + String _name_3 = execution.getLifeline().getExecutor().getName(); + _builder_1.append(_name_3); + _switchResult = _builder_1.toString(); + break; + default: + StringConcatenation _builder_2 = new StringConcatenation(); + _builder_2.append("Unsupported configuration: "); + _builder_2.append(configuration); + _switchResult = _builder_2.toString(); + break; + } + } else { + StringConcatenation _builder_2 = new StringConcatenation(); + _builder_2.append("Unsupported configuration: "); + _builder_2.append(configuration); + _switchResult = _builder_2.toString(); + } + return _switchResult; + } + + @Override + public Iterable getSiblings(final Object object, final String configuration) { + final Execution execution = ((Execution) object); + return TmscQueries.findAllWithFunctionAndLifeline(execution); + } + + @Override + public Long getDuration(final Object object, final Object sibling, final String configuration) { + final Execution execution = ((Execution) sibling); + long _switchResult = (long) 0; + if (configuration != null) { + switch (configuration) { + case ExecutionDataAnalysisItemContentProvider.CONF_ON_CPU: + _switchResult = TmscCpuInfoQueries.getOnCpuNanos(execution, true); + break; + case ExecutionDataAnalysisItemContentProvider.CONF_WAIT_CPU: + _switchResult = TmscCpuInfoQueries.getWaitCpuNanos(execution, true); + break; + default: + StringConcatenation _builder = new StringConcatenation(); + _builder.append("Unsupported configuration: "); + _builder.append(configuration); + throw new IllegalArgumentException(_builder.toString()); + } + } else { + StringConcatenation _builder = new StringConcatenation(); + _builder.append("Unsupported configuration: "); + _builder.append(configuration); + throw new IllegalArgumentException(_builder.toString()); + } + return Long.valueOf(_switchResult); + } +} diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/.classpath b/plugins/nl.esi.pps.tmsc.cpu.editor/.classpath new file mode 100644 index 0000000..c001577 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/.project b/plugins/nl.esi.pps.tmsc.cpu.editor/.project new file mode 100644 index 0000000..4f0d8ca --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/.project @@ -0,0 +1,28 @@ + + + nl.esi.pps.tmsc.cpu.editor + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/.settings/org.eclipse.core.resources.prefs b/plugins/nl.esi.pps.tmsc.cpu.editor/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/.settings/org.eclipse.jdt.core.prefs b/plugins/nl.esi.pps.tmsc.cpu.editor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..23fa13b --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/META-INF/MANIFEST.MF b/plugins/nl.esi.pps.tmsc.cpu.editor/META-INF/MANIFEST.MF new file mode 100644 index 0000000..5704106 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: TMSC CPU Editor +Bundle-SymbolicName: nl.esi.pps.tmsc.cpu.editor;singleton:=true +Bundle-Vendor: ESI (TNO) +Bundle-Version: 0.30.0.qualifier +Require-Bundle: nl.esi.pps.tmsc.cpu, + nl.esi.pps.tmsc.editor, + nl.esi.pps, + org.eclipse.lsat.common.queries +Automatic-Module-Name: nl.esi.pps.tmsc.cpu.editor +Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/build.properties b/plugins/nl.esi.pps.tmsc.cpu.editor/build.properties new file mode 100644 index 0000000..c0ee467 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/build.properties @@ -0,0 +1,16 @@ +# +# Copyright (c) 2018-2025 TNO and Contributors to the GitHub community +# +# This program and the accompanying materials are made available +# under the terms of the MIT License which is available at +# https://opensource.org/licenses/MIT +# +# SPDX-License-Identifier: MIT +# + +source.. = src/ +output.. = target/classes/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + icons/ diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/icons/cpu.png b/plugins/nl.esi.pps.tmsc.cpu.editor/icons/cpu.png new file mode 100644 index 0000000..716ba39 Binary files /dev/null and b/plugins/nl.esi.pps.tmsc.cpu.editor/icons/cpu.png differ diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/plugin.xml b/plugins/nl.esi.pps.tmsc.cpu.editor/plugin.xml new file mode 100644 index 0000000..727c374 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/plugin.xml @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/src/nl/esi/pps/tmsc/cpu/editor/plot/CpuInfoRenderingKey.java b/plugins/nl.esi.pps.tmsc.cpu.editor/src/nl/esi/pps/tmsc/cpu/editor/plot/CpuInfoRenderingKey.java new file mode 100644 index 0000000..9419722 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/src/nl/esi/pps/tmsc/cpu/editor/plot/CpuInfoRenderingKey.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu.editor.plot; + +import java.awt.Color; +import java.awt.Paint; + +import nl.esi.pps.tmsc.rendering.plot.IRenderingSeriesConfigurator; +import nl.esi.pps.tmsc.viewers.plot.ExecutionsRenderer; + +public enum CpuInfoRenderingKey implements IRenderingSeriesConfigurator { + ON_CPU("On-CPU", new Color(0, 183, 185)), + WAIT_CPU("Wait-for-CPU", new Color(234, 0, 94)), + WAIT_OTHER("Wait-Other", new Color(174, 182, 193)); + + private final String literal; + private final Paint paint; + + private CpuInfoRenderingKey(String literal, Paint paint) { + this.literal = literal; + this.paint = paint; + } + + @Override + public void configureExecutionsSeries(ExecutionsRenderer executionsRenderer, int series, boolean notify) { + executionsRenderer.setSeriesVisibleInLegend(series, true, notify); + executionsRenderer.setSeriesPaint(series, paint, notify); + } + + @Override + public String toString() { + return literal; + } +} diff --git a/plugins/nl.esi.pps.tmsc.cpu.editor/src/nl/esi/pps/tmsc/cpu/editor/plot/CpuInfoRenderingStrategy.java b/plugins/nl.esi.pps.tmsc.cpu.editor/src/nl/esi/pps/tmsc/cpu/editor/plot/CpuInfoRenderingStrategy.java new file mode 100644 index 0000000..cb051f8 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu.editor/src/nl/esi/pps/tmsc/cpu/editor/plot/CpuInfoRenderingStrategy.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu.editor.plot; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.lsat.common.queries.QueryableIterable; +import org.eclipse.trace4cps.common.jfreechart.chart.axis.Section; +import org.eclipse.trace4cps.common.jfreechart.chart.axis.SectionAxis; +import org.eclipse.trace4cps.common.jfreechart.data.xy.XYEdgeSeriesCollection; +import org.eclipse.trace4cps.common.jfreechart.ui.gantt.XYGanttDataItem; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.Range; +import org.jfree.data.xy.XYIntervalSeriesCollection; + +import nl.esi.pps.preferences.PPSPreferences; +import nl.esi.pps.tmsc.Dependency; +import nl.esi.pps.tmsc.Execution; +import nl.esi.pps.tmsc.FullScopeTMSC; +import nl.esi.pps.tmsc.Lifeline; +import nl.esi.pps.tmsc.LifelineSegment; +import nl.esi.pps.tmsc.cpu.TmscCpuInfoQueries; +import nl.esi.pps.tmsc.rendering.plot.EnumRenderingStrategy; +import nl.esi.pps.tmsc.rendering.plot.EnumRenderingStrategy.VoidRenderingKey; +import nl.esi.pps.tmsc.viewers.plot.DependenciesRenderer; +import nl.esi.pps.tmsc.viewers.plot.DependencyDataItem; +import nl.esi.pps.tmsc.viewers.plot.ExecutionDataItem; +import nl.esi.pps.tmsc.viewers.plot.ExecutionsRenderer; + +public class CpuInfoRenderingStrategy extends EnumRenderingStrategy { + private XYIntervalSeriesCollection executionsDataset; + private Map lifelineRanges; + + public CpuInfoRenderingStrategy() { + super(CpuInfoRenderingKey.class, VoidRenderingKey.class); + } + + @Override + public boolean isSupported(EditingDomain editingDomain) { + return PPSPreferences.isAdvancedFeaturesEnabled() && + QueryableIterable.from(editingDomain.getResourceSet().getResources()) + .collect(Resource::getContents) + .objectsOfKind(FullScopeTMSC.class) + .exists(TmscCpuInfoQueries::hasCpuInfo); + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element instanceof Lifeline lifeline) { + return TmscCpuInfoQueries.hasCpuInfo(lifeline); + } else if (element instanceof Execution execution) { + // Results in every lifeline getting 1 height unit + // Although we are not rendering executions, we need the root level executions + // in order for the lifeline to be rendered. + return execution.getParent() == null; + } else if (element instanceof LifelineSegment segment) { + return segment.getStartTime() != null && segment.getEndTime() != null; + } else if (element instanceof Dependency) { + return false; + } + return super.select(viewer, parentElement, element); + } + + @Override + public void preRendering(XYEdgeSeriesCollection dependenciesDataset, DependenciesRenderer dependenciesRenderer, + XYIntervalSeriesCollection executionsDataset, ExecutionsRenderer executionsRenderer) { + this.executionsDataset = executionsDataset; + this.lifelineRanges = new HashMap<>(); + super.preRendering(dependenciesDataset, dependenciesRenderer, executionsDataset, executionsRenderer); + } + + @Override + public Section addLifelineSection(SectionAxis axis, Lifeline lifeline, String label, double length) { + Section section = super.addLifelineSection(axis, lifeline, label, 10); + section.setGridBandNumberRange(new Range(0, 100), true); + this.lifelineRanges.put(lifeline, section.getRange()); + return section; + } + + @Override + public void postRendering(XYEdgeSeriesCollection dependenciesDataset, DependenciesRenderer dependenciesRenderer, + XYIntervalSeriesCollection executionsDataset, ExecutionsRenderer executionsRenderer) { + super.postRendering(dependenciesDataset, dependenciesRenderer, executionsDataset, executionsRenderer); + executionsRenderer.setDefaultItemLabelsVisible(false); + executionsRenderer.setDrawBarOutline(false); + this.executionsDataset = null; + this.lifelineRanges = null; + } + + @Override + public void add(ExecutionDataItem executionDataItem, XYIntervalSeriesCollection executionsDataset, + ExecutionsRenderer executionsRenderer) { + // We are not rendering the root executions, but we need them for the life-line to be rendered. + // super.add(executionDataItem, executionsDataset, executionsRenderer); + } + + @Override + public void add(DependencyDataItem dataItem, XYEdgeSeriesCollection dataSet, DependenciesRenderer renderer) { + Dependency dependency = dataItem.getBackReference(); + if (dependency instanceof LifelineSegment segment) { + Range cpuSectionRange = lifelineRanges.get(segment.getLifeline()); + if (cpuSectionRange == null) { + return; + } + + BigDecimal cpuOffset = BigDecimal.ZERO; + long onCpuNanos = TmscCpuInfoQueries.getOnCpuNanos(segment); + if (onCpuNanos > 0) { + BigDecimal cpuOccupation = BigDecimal.valueOf(onCpuNanos) + .divide(BigDecimal.valueOf(segment.getDuration()), 10, RoundingMode.HALF_UP); + XYGanttDataItem item = new XYGanttDataItem<>(cpuSectionRange, cpuOccupation, + cpuOffset, dataItem.getX0(), dataItem.getX1(), PlotOrientation.VERTICAL, segment); + this.executionsDataset.getSeries(getSeries(CpuInfoRenderingKey.ON_CPU)).add(item, true); + cpuOffset = cpuOffset.add(cpuOccupation); + } + long waitCpuNanos = TmscCpuInfoQueries.getWaitCpuNanos(segment); + if (waitCpuNanos > 0) { + BigDecimal cpuOccupation = BigDecimal.valueOf(waitCpuNanos) + .divide(BigDecimal.valueOf(segment.getDuration()), 10, RoundingMode.HALF_UP); + XYGanttDataItem item = new XYGanttDataItem<>(cpuSectionRange, cpuOccupation, + cpuOffset, dataItem.getX0(), dataItem.getX1(), PlotOrientation.VERTICAL, segment); + this.executionsDataset.getSeries(getSeries(CpuInfoRenderingKey.WAIT_CPU)).add(item, true); + cpuOffset = cpuOffset.add(cpuOccupation); + } + long waitOtherNanos = TmscCpuInfoQueries.getWaitOtherNanos(segment); + if (waitOtherNanos > 0) { + BigDecimal cpuOccupation = BigDecimal.valueOf(waitOtherNanos) + .divide(BigDecimal.valueOf(segment.getDuration()), 10, RoundingMode.HALF_UP); + XYGanttDataItem item = new XYGanttDataItem<>(cpuSectionRange, cpuOccupation, + cpuOffset, dataItem.getX0(), dataItem.getX1(), PlotOrientation.VERTICAL, segment); + this.executionsDataset.getSeries(getSeries(CpuInfoRenderingKey.WAIT_OTHER)).add(item, true); + cpuOffset = cpuOffset.add(cpuOccupation); + } + } + } + + @Override + protected CpuInfoRenderingKey getRenderingKey(Execution execution) { + // Not used, not showing executions + return null; + } + + @Override + protected VoidRenderingKey getRenderingKey(Dependency dependency) { + // Not used, not showing dependencies + return null; + } +} diff --git a/plugins/nl.esi.pps.tmsc.cpu/.classpath b/plugins/nl.esi.pps.tmsc.cpu/.classpath new file mode 100644 index 0000000..2b8bad5 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/plugins/nl.esi.pps.tmsc.cpu/.project b/plugins/nl.esi.pps.tmsc.cpu/.project new file mode 100644 index 0000000..5ab6d8d --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/.project @@ -0,0 +1,34 @@ + + + nl.esi.pps.tmsc.cpu + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/plugins/nl.esi.pps.tmsc.cpu/.settings/org.eclipse.core.resources.prefs b/plugins/nl.esi.pps.tmsc.cpu/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/plugins/nl.esi.pps.tmsc.cpu/.settings/org.eclipse.jdt.core.prefs b/plugins/nl.esi.pps.tmsc.cpu/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..23fa13b --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/plugins/nl.esi.pps.tmsc.cpu/META-INF/MANIFEST.MF b/plugins/nl.esi.pps.tmsc.cpu/META-INF/MANIFEST.MF new file mode 100644 index 0000000..e4c9f83 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/META-INF/MANIFEST.MF @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: TMSC CPU +Bundle-SymbolicName: nl.esi.pps.tmsc.cpu +Bundle-Version: 0.30.0.qualifier +Export-Package: nl.esi.pps.tmsc.cpu +Require-Bundle: nl.esi.pps.tmsc;visibility:=reexport, + org.eclipse.lsat.common.xtend +Bundle-Vendor: ESI (TNO) +Automatic-Module-Name: nl.esi.pps.tmsc.cpu +Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/plugins/nl.esi.pps.tmsc.cpu/build.properties b/plugins/nl.esi.pps.tmsc.cpu/build.properties new file mode 100644 index 0000000..3bfbd1f --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/build.properties @@ -0,0 +1,15 @@ +# +# Copyright (c) 2018-2025 TNO and Contributors to the GitHub community +# +# This program and the accompanying materials are made available +# under the terms of the MIT License which is available at +# https://opensource.org/licenses/MIT +# +# SPDX-License-Identifier: MIT +# + +source.. = src/,\ + xtend-gen/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/plugins/nl.esi.pps.tmsc.cpu/src/nl/esi/pps/tmsc/cpu/TmscCpuInfoProjection.xtend b/plugins/nl.esi.pps.tmsc.cpu/src/nl/esi/pps/tmsc/cpu/TmscCpuInfoProjection.xtend new file mode 100644 index 0000000..784c1c2 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/src/nl/esi/pps/tmsc/cpu/TmscCpuInfoProjection.xtend @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu + +import java.util.Map +import nl.esi.pps.tmsc.Dependency +import nl.esi.pps.tmsc.Event +import nl.esi.pps.tmsc.LifelineSegment +import nl.esi.pps.tmsc.util.DependencyFeatureProjection +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor + +import static extension nl.esi.pps.tmsc.cpu.TmscCpuInfoQueries.* + +class TmscCpuInfoProjection { + public static val ON_CPU_PROJECTION = new LifelineSegmentCpuInfoProjection([onCpuNanos],[$0.onCpuNanos = $1]) + public static val WAIT_CPU_PROJECTION = new LifelineSegmentCpuInfoProjection([waitCpuNanos],[$0.waitCpuNanos = $1]) + public static val WAIT_OTHER_PROJECTION = new LifelineSegmentCpuInfoProjection([waitOtherNanos],[$0.waitOtherNanos = $1]) + + private new() { + // Empty for utility classes + } + + @FinalFieldsConstructor + private static class LifelineSegmentCpuInfoProjection implements DependencyFeatureProjection { + val (LifelineSegment)=>long getter + val (LifelineSegment, long)=>void setter + + override getInitialValue(Event projectionSource) { + return 0L + } + + override calculateProjectedValue(Event projectionSource, Map projectionValues) { + val validProjectionValues = projectionValues.entrySet.filter[key instanceof LifelineSegment].reject[key.projection || value === null] + return switch (it: validProjectionValues) { + case isEmpty: null + case size == 1: head.value + getter.apply(head.key as LifelineSegment) + default: throw new IllegalStateException('Programming error, please contact PPS support!') + } + } + + override apply(Dependency projection, Long projectedValue) { + if (projection instanceof LifelineSegment) { + if (getter.apply(projection) > 0 && getter.apply(projection) != projectedValue) { + // Expected the same onCpuNanos to be calculated if projection is reused + throw new IllegalArgumentException('Programming error, please contact PPS support!') + } + setter.apply(projection, projectedValue ?: 0L) + } + } + } +} \ No newline at end of file diff --git a/plugins/nl.esi.pps.tmsc.cpu/src/nl/esi/pps/tmsc/cpu/TmscCpuInfoQueries.xtend b/plugins/nl.esi.pps.tmsc.cpu/src/nl/esi/pps/tmsc/cpu/TmscCpuInfoQueries.xtend new file mode 100644 index 0000000..8d42946 --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/src/nl/esi/pps/tmsc/cpu/TmscCpuInfoQueries.xtend @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu + +import nl.esi.emf.properties.xtend.PersistedProperty +import nl.esi.pps.tmsc.Execution +import nl.esi.pps.tmsc.FullScopeTMSC +import nl.esi.pps.tmsc.Lifeline +import nl.esi.pps.tmsc.LifelineSegment + +import static extension nl.esi.pps.tmsc.util.TmscQueries.* + +class TmscCpuInfoQueries { + @PersistedProperty(LifelineSegment) + public static val long onCpuNanos = 0L + + @PersistedProperty(LifelineSegment) + public static val long waitCpuNanos = 0L + + @PersistedProperty(LifelineSegment) + public static val long waitOtherNanos = 0L + + static def long getOnCpuNanos(Execution execution, boolean includeChildren) { + return execution.callStackLifelineSegments.fold(0L)[sum, segment | + return (includeChildren || segment.activeExecution === execution) ? sum + segment.onCpuNanos : sum + ] + } + + static def long getWaitCpuNanos(Execution execution, boolean includeChildren) { + return execution.callStackLifelineSegments.fold(0L)[sum, segment | + return (includeChildren || segment.activeExecution === execution) ? sum + segment.waitCpuNanos : sum + ] + } + + static def long getWaitOtherNanos(Execution execution, boolean includeChildren) { + return execution.callStackLifelineSegments.fold(0L)[sum, segment | + return (includeChildren || segment.activeExecution === execution) ? sum + segment.waitOtherNanos : sum + ] + } + + static def boolean hasCpuInfo(FullScopeTMSC tmsc) { + return tmsc.dependencies.filter(LifelineSegment).exists[hasCpuInfo] + } + + static def boolean hasCpuInfo(Lifeline lifeline) { + return lifeline.segments.exists[hasCpuInfo] + } + + static def boolean hasCpuInfo(Execution execution) { + return execution.callStackLifelineSegments.exists[hasCpuInfo] + } + + static def boolean hasCpuInfo(LifelineSegment segement) { + return segement.onCpuNanos > 0 || segement.waitCpuNanos > 0 || segement.waitOtherNanos > 0 + } + + static def void clearCpuInfo(FullScopeTMSC tmsc) { + tmsc.dependencies.filter(LifelineSegment).forEach[clearCpuInfo] + } + + static def void clearCpuInfo(Lifeline lifeline) { + lifeline.segments.forEach[clearCpuInfo] + } + + static def void clearCpuInfo(Execution execution) { + execution.callStackLifelineSegments.forEach[clearCpuInfo] + } + + static def void clearCpuInfo(LifelineSegment segement) { + segement.onCpuNanos = 0L + segement.waitCpuNanos = 0L + segement.waitOtherNanos = 0L + } +} \ No newline at end of file diff --git a/plugins/nl.esi.pps.tmsc.cpu/xtend-gen/nl/esi/pps/tmsc/cpu/TmscCpuInfoProjection.java b/plugins/nl.esi.pps.tmsc.cpu/xtend-gen/nl/esi/pps/tmsc/cpu/TmscCpuInfoProjection.java new file mode 100644 index 0000000..1d2184b --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/xtend-gen/nl/esi/pps/tmsc/cpu/TmscCpuInfoProjection.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu; + +import java.util.Map; +import java.util.Objects; +import nl.esi.pps.tmsc.Dependency; +import nl.esi.pps.tmsc.Event; +import nl.esi.pps.tmsc.LifelineSegment; +import nl.esi.pps.tmsc.util.DependencyFeatureProjection; +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.IterableExtensions; +import org.eclipse.xtext.xbase.lib.Procedures.Procedure2; + +@SuppressWarnings("all") +public class TmscCpuInfoProjection { + @FinalFieldsConstructor + private static class LifelineSegmentCpuInfoProjection implements DependencyFeatureProjection { + private final Function1 getter; + + private final Procedure2 setter; + + @Override + public Long getInitialValue(final Event projectionSource) { + return Long.valueOf(0L); + } + + @Override + public Long calculateProjectedValue(final Event projectionSource, final Map projectionValues) { + final Function1, Boolean> _function = (Map.Entry it) -> { + Dependency _key = it.getKey(); + return Boolean.valueOf((_key instanceof LifelineSegment)); + }; + final Function1, Boolean> _function_1 = (Map.Entry it) -> { + return Boolean.valueOf((it.getKey().isProjection() || (it.getValue() == null))); + }; + final Iterable> validProjectionValues = IterableExtensions.>reject(IterableExtensions.>filter(projectionValues.entrySet(), _function), _function_1); + Long _switchResult = null; + final Iterable> it = validProjectionValues; + boolean _matched = false; + boolean _isEmpty = IterableExtensions.isEmpty(it); + if (_isEmpty) { + _matched=true; + _switchResult = null; + } + if (!_matched) { + int _size = IterableExtensions.size(it); + boolean _equals = (_size == 1); + if (_equals) { + _matched=true; + Long _value = IterableExtensions.>head(it).getValue(); + Dependency _key = IterableExtensions.>head(it).getKey(); + Long _apply = this.getter.apply(((LifelineSegment) _key)); + _switchResult = Long.valueOf(((_value).longValue() + (_apply).longValue())); + } + } + if (!_matched) { + throw new IllegalStateException("Programming error, please contact PPS support!"); + } + return _switchResult; + } + + @Override + public void apply(final Dependency projection, final Long projectedValue) { + if ((projection instanceof LifelineSegment)) { + if ((((this.getter.apply(((LifelineSegment)projection))).longValue() > 0) && (!Objects.equals(this.getter.apply(((LifelineSegment)projection)), projectedValue)))) { + throw new IllegalArgumentException("Programming error, please contact PPS support!"); + } + Long _elvis = null; + if (projectedValue != null) { + _elvis = projectedValue; + } else { + _elvis = Long.valueOf(0L); + } + this.setter.apply(((LifelineSegment)projection), _elvis); + } + } + + public LifelineSegmentCpuInfoProjection(final Function1 getter, final Procedure2 setter) { + super(); + this.getter = getter; + this.setter = setter; + } + } + + public static final TmscCpuInfoProjection.LifelineSegmentCpuInfoProjection ON_CPU_PROJECTION = new TmscCpuInfoProjection.LifelineSegmentCpuInfoProjection(((Function1) (LifelineSegment it) -> { + return Long.valueOf(TmscCpuInfoQueries.getOnCpuNanos(it)); + }), ((Procedure2) (LifelineSegment $0, Long $1) -> { + TmscCpuInfoQueries.setOnCpuNanos($0, ($1).longValue()); + })); + + public static final TmscCpuInfoProjection.LifelineSegmentCpuInfoProjection WAIT_CPU_PROJECTION = new TmscCpuInfoProjection.LifelineSegmentCpuInfoProjection(((Function1) (LifelineSegment it) -> { + return Long.valueOf(TmscCpuInfoQueries.getWaitCpuNanos(it)); + }), ((Procedure2) (LifelineSegment $0, Long $1) -> { + TmscCpuInfoQueries.setWaitCpuNanos($0, ($1).longValue()); + })); + + public static final TmscCpuInfoProjection.LifelineSegmentCpuInfoProjection WAIT_OTHER_PROJECTION = new TmscCpuInfoProjection.LifelineSegmentCpuInfoProjection(((Function1) (LifelineSegment it) -> { + return Long.valueOf(TmscCpuInfoQueries.getWaitOtherNanos(it)); + }), ((Procedure2) (LifelineSegment $0, Long $1) -> { + TmscCpuInfoQueries.setWaitOtherNanos($0, ($1).longValue()); + })); + + private TmscCpuInfoProjection() { + } +} diff --git a/plugins/nl.esi.pps.tmsc.cpu/xtend-gen/nl/esi/pps/tmsc/cpu/TmscCpuInfoQueries.java b/plugins/nl.esi.pps.tmsc.cpu/xtend-gen/nl/esi/pps/tmsc/cpu/TmscCpuInfoQueries.java new file mode 100644 index 0000000..535554e --- /dev/null +++ b/plugins/nl.esi.pps.tmsc.cpu/xtend-gen/nl/esi/pps/tmsc/cpu/TmscCpuInfoQueries.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2018-2025 TNO and Contributors to the GitHub community + * + * This program and the accompanying materials are made available + * under the terms of the MIT License which is available at + * https://opensource.org/licenses/MIT + * + * SPDX-License-Identifier: MIT + */ +package nl.esi.pps.tmsc.cpu; + +import com.google.common.collect.Iterables; +import java.util.function.Consumer; +import nl.esi.pps.tmsc.Execution; +import nl.esi.pps.tmsc.FullScopeTMSC; +import nl.esi.pps.tmsc.Lifeline; +import nl.esi.pps.tmsc.LifelineSegment; +import nl.esi.pps.tmsc.util.TmscQueries; +import org.eclipse.xtext.xbase.lib.Functions.Function1; +import org.eclipse.xtext.xbase.lib.Functions.Function2; +import org.eclipse.xtext.xbase.lib.IterableExtensions; + +@SuppressWarnings("all") +public class TmscCpuInfoQueries { + public static long getOnCpuNanos(final Execution execution, final boolean includeChildren) { + final Function2 _function = (Long sum, LifelineSegment segment) -> { + Long _xifexpression = null; + if ((includeChildren || (segment.getActiveExecution() == execution))) { + long _onCpuNanos = TmscCpuInfoQueries.getOnCpuNanos(segment); + _xifexpression = Long.valueOf(((sum).longValue() + _onCpuNanos)); + } else { + _xifexpression = sum; + } + return _xifexpression; + }; + return (long) IterableExtensions.fold(TmscQueries.getCallStackLifelineSegments(execution), Long.valueOf(0L), _function); + } + + public static long getWaitCpuNanos(final Execution execution, final boolean includeChildren) { + final Function2 _function = (Long sum, LifelineSegment segment) -> { + Long _xifexpression = null; + if ((includeChildren || (segment.getActiveExecution() == execution))) { + long _waitCpuNanos = TmscCpuInfoQueries.getWaitCpuNanos(segment); + _xifexpression = Long.valueOf(((sum).longValue() + _waitCpuNanos)); + } else { + _xifexpression = sum; + } + return _xifexpression; + }; + return (long) IterableExtensions.fold(TmscQueries.getCallStackLifelineSegments(execution), Long.valueOf(0L), _function); + } + + public static long getWaitOtherNanos(final Execution execution, final boolean includeChildren) { + final Function2 _function = (Long sum, LifelineSegment segment) -> { + Long _xifexpression = null; + if ((includeChildren || (segment.getActiveExecution() == execution))) { + long _waitOtherNanos = TmscCpuInfoQueries.getWaitOtherNanos(segment); + _xifexpression = Long.valueOf(((sum).longValue() + _waitOtherNanos)); + } else { + _xifexpression = sum; + } + return _xifexpression; + }; + return (long) IterableExtensions.fold(TmscQueries.getCallStackLifelineSegments(execution), Long.valueOf(0L), _function); + } + + public static boolean hasCpuInfo(final FullScopeTMSC tmsc) { + final Function1 _function = (LifelineSegment it) -> { + return Boolean.valueOf(TmscCpuInfoQueries.hasCpuInfo(it)); + }; + return IterableExtensions.exists(Iterables.filter(tmsc.getDependencies(), LifelineSegment.class), _function); + } + + public static boolean hasCpuInfo(final Lifeline lifeline) { + final Function1 _function = (LifelineSegment it) -> { + return Boolean.valueOf(TmscCpuInfoQueries.hasCpuInfo(it)); + }; + return IterableExtensions.exists(lifeline.getSegments(), _function); + } + + public static boolean hasCpuInfo(final Execution execution) { + final Function1 _function = (LifelineSegment it) -> { + return Boolean.valueOf(TmscCpuInfoQueries.hasCpuInfo(it)); + }; + return IterableExtensions.exists(TmscQueries.getCallStackLifelineSegments(execution), _function); + } + + public static boolean hasCpuInfo(final LifelineSegment segement) { + return (((TmscCpuInfoQueries.getOnCpuNanos(segement) > 0) || (TmscCpuInfoQueries.getWaitCpuNanos(segement) > 0)) || (TmscCpuInfoQueries.getWaitOtherNanos(segement) > 0)); + } + + public static void clearCpuInfo(final FullScopeTMSC tmsc) { + final Consumer _function = (LifelineSegment it) -> { + TmscCpuInfoQueries.clearCpuInfo(it); + }; + Iterables.filter(tmsc.getDependencies(), LifelineSegment.class).forEach(_function); + } + + public static void clearCpuInfo(final Lifeline lifeline) { + final Consumer _function = (LifelineSegment it) -> { + TmscCpuInfoQueries.clearCpuInfo(it); + }; + lifeline.getSegments().forEach(_function); + } + + public static void clearCpuInfo(final Execution execution) { + final Consumer _function = (LifelineSegment it) -> { + TmscCpuInfoQueries.clearCpuInfo(it); + }; + TmscQueries.getCallStackLifelineSegments(execution).forEach(_function); + } + + public static void clearCpuInfo(final LifelineSegment segement) { + TmscCpuInfoQueries.setOnCpuNanos(segement, 0L); + TmscCpuInfoQueries.setWaitCpuNanos(segement, 0L); + TmscCpuInfoQueries.setWaitOtherNanos(segement, 0L); + } + + /** + * Default value for persisted {@code onCpuNanos} property on LifelineSegment + */ + private static final long _DEFAULT_LIFELINESEGMENT_ONCPUNANOS = 0L; + + public static long getOnCpuNanos(final LifelineSegment container) { + final String key = "onCpuNanos"; + final Object value = container.getProperties().get(key); + if (value == null) { + return _DEFAULT_LIFELINESEGMENT_ONCPUNANOS; + } + return (long) value; + } + + public static void setOnCpuNanos(final LifelineSegment container, final long value) { + final String key = "onCpuNanos"; + if (value == _DEFAULT_LIFELINESEGMENT_ONCPUNANOS) { + container.getProperties().remove(key); + } else { + container.getProperties().put(key, value); + } + } + + /** + * Default value for persisted {@code waitCpuNanos} property on LifelineSegment + */ + private static final long _DEFAULT_LIFELINESEGMENT_WAITCPUNANOS = 0L; + + public static long getWaitCpuNanos(final LifelineSegment container) { + final String key = "waitCpuNanos"; + final Object value = container.getProperties().get(key); + if (value == null) { + return _DEFAULT_LIFELINESEGMENT_WAITCPUNANOS; + } + return (long) value; + } + + public static void setWaitCpuNanos(final LifelineSegment container, final long value) { + final String key = "waitCpuNanos"; + if (value == _DEFAULT_LIFELINESEGMENT_WAITCPUNANOS) { + container.getProperties().remove(key); + } else { + container.getProperties().put(key, value); + } + } + + /** + * Default value for persisted {@code waitOtherNanos} property on LifelineSegment + */ + private static final long _DEFAULT_LIFELINESEGMENT_WAITOTHERNANOS = 0L; + + public static long getWaitOtherNanos(final LifelineSegment container) { + final String key = "waitOtherNanos"; + final Object value = container.getProperties().get(key); + if (value == null) { + return _DEFAULT_LIFELINESEGMENT_WAITOTHERNANOS; + } + return (long) value; + } + + public static void setWaitOtherNanos(final LifelineSegment container, final long value) { + final String key = "waitOtherNanos"; + if (value == _DEFAULT_LIFELINESEGMENT_WAITOTHERNANOS) { + container.getProperties().remove(key); + } else { + container.getProperties().put(key, value); + } + } +} diff --git a/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/AbstractRenderingStrategy.java b/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/AbstractRenderingStrategy.java index d7ee711..ee0e902 100644 --- a/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/AbstractRenderingStrategy.java +++ b/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/AbstractRenderingStrategy.java @@ -75,6 +75,7 @@ public void preRendering(XYEdgeSeriesCollection dependenciesDataset, Dependencie } protected void resetRenderer(DependenciesRenderer dependenciesRenderer) { + dependenciesRenderer.setDefaultItemLabelsVisible(false); dependenciesRenderer.setComputeItemLabelContrastColor(true); dependenciesRenderer.setDefaultSeriesVisibleInLegend(false); @@ -97,6 +98,7 @@ protected void resetRenderer(DependenciesRenderer dependenciesRenderer) { } protected void resetRenderer(ExecutionsRenderer executionsRenderer) { + executionsRenderer.setDefaultItemLabelsVisible(true); executionsRenderer.setComputeItemLabelContrastColor(true); executionsRenderer.setDefaultSeriesVisibleInLegend(false); @@ -108,6 +110,7 @@ protected void resetRenderer(ExecutionsRenderer executionsRenderer) { executionsRenderer.clearSeriesOutlinePaints(false); executionsRenderer.setDefaultPaintSupplier(RenderingPaint.CONTROL, false); + executionsRenderer.setDrawBarOutline(true); executionsRenderer.setAutoPopulateSeriesOutlineStroke(false); executionsRenderer.setDefaultOutlineStroke(RenderingStroke.FINE_SOLID.getStroke()); } diff --git a/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/IRenderingStrategy.java b/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/IRenderingStrategy.java index 81979a4..5b17589 100644 --- a/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/IRenderingStrategy.java +++ b/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/rendering/plot/IRenderingStrategy.java @@ -12,6 +12,7 @@ import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jface.viewers.Viewer; import org.eclipse.trace4cps.common.jfreechart.chart.axis.Section; +import org.eclipse.trace4cps.common.jfreechart.chart.axis.SectionAxis; import org.eclipse.trace4cps.common.jfreechart.data.xy.XYEdgeSeriesCollection; import org.jfree.data.xy.XYIntervalSeriesCollection; @@ -54,8 +55,8 @@ default boolean isSupported(EditingDomain editingDomain) { default boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof LifelineSegment) { return false; - } else if (element instanceof Dependency) { - return !((Dependency) element).isProjection(); + } else if (element instanceof Dependency dependency) { + return !dependency.isProjection(); } else { return true; } @@ -63,6 +64,12 @@ default boolean select(Viewer viewer, Object parentElement, Object element) { void preRendering(XYEdgeSeriesCollection dependenciesDataset, DependenciesRenderer dependenciesRenderer, XYIntervalSeriesCollection executionsDataset, ExecutionsRenderer executionsRenderer); + + default Section addLifelineSection(SectionAxis axis, Lifeline lifeline, String label, double length) { + final Section lifelineSection = axis.nextSection(label, length); + configureLifelineSection(lifeline, lifelineSection); + return lifelineSection; + } void configureLifelineSection(Lifeline lifeline, Section section); diff --git a/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/viewers/TmscPlotViewer.java b/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/viewers/TmscPlotViewer.java index e281c68..cb3cab7 100644 --- a/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/viewers/TmscPlotViewer.java +++ b/plugins/nl.esi.pps.tmsc.editor/src/nl/esi/pps/tmsc/viewers/TmscPlotViewer.java @@ -449,13 +449,13 @@ protected void refreshChart(Object element) { boolean lifelineRendered = !lifeLineExecutions.isEmpty() || (lifeline.getExecutions().isEmpty() && !lifeline.getEvents().isEmpty()); if (lifelineRendered) { - Section lifelineSection = rangeAxis.nextSection(getLabelProvider().getText(lifeline), - getLifelineLength(lifeLineExecutions)); + Section lifelineSection = renderingStrategy.addLifelineSection(rangeAxis, lifeline, + getLabelProvider().getText(lifeline), getLifelineLength(lifeLineExecutions)); lifelineRanges.put(lifeline, lifelineSection.getRange()); - renderingStrategy.configureLifelineSection(lifeline, lifelineSection); for (Execution execution : lifeLineExecutions) { - Range executionRange = getExecutionRange(execution, lifelineSection.getRange()); + Range executionRange = getCallStackLevelRange(getCallStackLevel(execution), + lifelineSection.getRange()); Double executionStart = getEventX(execution.getEntry()); Double executionEnd = getEventX(execution.getExit()); renderingStrategy.add( @@ -639,18 +639,24 @@ private Double getEventY(Event event) { if (event == null) { return null; } - Range eventYRange = lifelineRanges.get(event.getLifeline()); - if (eventYRange != null && event.getExecution() != null) { - eventYRange = getExecutionRange(event.getExecution(), eventYRange); + Range lifelineRange = lifelineRanges.get(event.getLifeline()); + if (lifelineRange == null) { + return null; + } + Execution execution = event.getExecution(); + if (execution == null) { + return lifelineRange.getCentralValue(); } - return eventYRange == null ? null : eventYRange.getCentralValue(); + int callStackLevel = + Math.max(filter(from(execution).climbTree(true, Execution::getParent).toArray()).length - 1, 0); + return getCallStackLevelRange(callStackLevel, lifelineRange).getCentralValue(); } /** * The component range will be equal to the stack size of the component + 0.1 * for padding. * - * @see #getExecutionRange(Execution, Range) + * @see #getCallStackLevelRange(Execution, Range) */ private double getLifelineLength(Iterable componentExecutions) { QueryableIterable callStackLevels = from(componentExecutions).xcollectOne(this::getCallStackLevel); @@ -662,15 +668,18 @@ private double getLifelineLength(Iterable componentExecutions) { /** * @see #getLifelineLength(Iterable) */ - private Range getExecutionRange(Execution execution, Range componentRange) { - Integer callStackLevel = getCallStackLevel(execution); - if (callStackLevel == null) { - // Execution is not visible + private Range getCallStackLevelRange(Integer callStackLevel, Range componentRange) { + if (callStackLevel == null || componentRange == null) { return null; } // Add 0.1 for resource padding - double executionLower = componentRange.getLowerBound() + callStackLevel + 0.1; - return new Range(executionLower, executionLower + 1); + double callStackLower = componentRange.getLowerBound() + callStackLevel + 0.1; + Range callStackRange = new Range(callStackLower, callStackLower + 1); + if (!componentRange.contains(callStackRange)) { + throw new IllegalArgumentException( + "Call-stack " + callStackRange + " doesn't fit in component " + componentRange); + } + return new Range(callStackLower, callStackLower + 1); } private Integer getCallStackLevel(Execution execution) { diff --git a/products/nl.esi.pps.product/category.xml b/products/nl.esi.pps.product/category.xml index 13d6db2..fbd0d29 100644 --- a/products/nl.esi.pps.product/category.xml +++ b/products/nl.esi.pps.product/category.xml @@ -41,6 +41,12 @@ + + + + + + diff --git a/releng/nl.esi.pps.target/nl.esi.pps.target.target b/releng/nl.esi.pps.target/nl.esi.pps.target.target index 4b52c5b..e4a80b3 100644 --- a/releng/nl.esi.pps.target/nl.esi.pps.target.target +++ b/releng/nl.esi.pps.target/nl.esi.pps.target.target @@ -1,6 +1,6 @@ - + @@ -133,12 +133,12 @@ + - @@ -164,7 +164,7 @@ - +