1 /**********************************************************************
2 * Copyright (c) 2014 Ericsson, École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Bernd Hufmann - Initial API and implementation
11 * Geneviève Bastien - Create and use base class for XY plots
12 **********************************************************************/
14 package org
.eclipse
.tracecompass
.internal
.lttng2
.ust
.ui
.views
.memusage
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
18 import java
.util
.Collections
;
19 import java
.util
.HashMap
;
20 import java
.util
.List
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.swt
.SWT
;
25 import org
.eclipse
.swt
.widgets
.Composite
;
26 import org
.eclipse
.swt
.widgets
.Display
;
27 import org
.eclipse
.tracecompass
.common
.core
.format
.DataSizeWithUnitFormat
;
28 import org
.eclipse
.tracecompass
.internal
.lttng2
.ust
.core
.analysis
.memory
.UstMemoryStrings
;
29 import org
.eclipse
.tracecompass
.internal
.lttng2
.ust
.ui
.Activator
;
30 import org
.eclipse
.tracecompass
.lttng2
.ust
.core
.analysis
.memory
.UstMemoryAnalysisModule
;
31 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
32 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
33 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
34 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
35 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
36 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
37 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.TmfStateSystemAnalysisModule
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
41 import org
.eclipse
.tracecompass
.tmf
.ui
.viewers
.xycharts
.linecharts
.TmfCommonXLineChartViewer
;
42 import org
.swtchart
.Chart
;
47 * @author Matthew Khouzam
49 public class MemoryUsageViewer
extends TmfCommonXLineChartViewer
{
51 private TmfStateSystemAnalysisModule fModule
= null;
53 private final Map
<Integer
, double[]> fYValues
= new HashMap
<>();
54 private final Map
<Integer
, Integer
> fMemoryQuarks
= new HashMap
<>();
55 private final Map
<Integer
, String
> fSeriesName
= new HashMap
<>();
57 // Timeout between updates in the updateData thread
58 private static final long BUILD_UPDATE_TIMEOUT
= 500;
66 public MemoryUsageViewer(Composite parent
) {
67 super(parent
, Messages
.MemoryUsageViewer_Title
, Messages
.MemoryUsageViewer_XAxis
, Messages
.MemoryUsageViewer_YAxis
);
68 Chart chart
= getSwtChart();
69 chart
.getLegend().setPosition(SWT
.LEFT
);
70 chart
.getAxisSet().getYAxis(0).getTick().setFormat(DataSizeWithUnitFormat
.getInstance());
74 protected void initializeDataSource() {
75 ITmfTrace trace
= getTrace();
77 fModule
= TmfTraceUtils
.getAnalysisModuleOfClass(trace
, TmfStateSystemAnalysisModule
.class, UstMemoryAnalysisModule
.ID
);
78 if (fModule
== null) {
86 protected void updateData(long start
, long end
, int nb
, IProgressMonitor monitor
) {
88 if (getTrace() == null || fModule
== null) {
91 if (!fModule
.waitForInitialization()) {
94 ITmfStateSystem ss
= fModule
.getStateSystem();
95 /* Don't wait for the module completion, when it's ready, we'll know */
100 double[] xvalues
= getXAxis(start
, end
, nb
);
104 boolean complete
= false;
105 long currentEnd
= Math
.max(ss
.getStartTime(), start
);
107 while (!complete
&& currentEnd
< end
) {
108 if (monitor
.isCanceled()) {
111 complete
= ss
.waitUntilBuilt(BUILD_UPDATE_TIMEOUT
);
112 currentEnd
= ss
.getCurrentEndTime();
113 List
<Integer
> tidQuarks
= ss
.getSubAttributes(-1, false);
114 long traceStart
= Math
.max(getStartTime(), ss
.getStartTime());
115 long traceEnd
= getEndTime();
116 long offset
= this.getTimeOffset();
118 /* Initialize quarks and series names */
119 long queryStart
= Math
.max(ss
.getStartTime(), start
);
120 List
<ITmfStateInterval
> fullState
= Collections
.emptyList();
121 if (queryStart
<= currentEnd
) {
122 fullState
= ss
.queryFullState(queryStart
);
123 for (int quark
: tidQuarks
) {
124 fYValues
.put(quark
, new double[xvalues
.length
]);
125 fMemoryQuarks
.put(quark
, ss
.getQuarkRelative(quark
, UstMemoryStrings
.UST_MEMORY_MEMORY_ATTRIBUTE
));
126 int procNameQuark
= ss
.getQuarkRelative(quark
, UstMemoryStrings
.UST_MEMORY_PROCNAME_ATTRIBUTE
);
127 String oldSeriesName
= fSeriesName
.get(quark
);
128 String seriesName
= null;
130 ITmfStateValue procnameValue
= fullState
.get(procNameQuark
).getStateValue();
131 String procname
= ""; //$NON-NLS-1$
132 if (!procnameValue
.isNull()) {
133 procname
= procnameValue
.unboxStr();
135 seriesName
= (procname
+ ' ' + '(' + ss
.getAttributeName(quark
) + ')').trim();
136 } catch (TimeRangeException e
) {
137 seriesName
= '(' + ss
.getAttributeName(quark
) + ')';
140 if (oldSeriesName
!= null && !oldSeriesName
.equals(seriesName
)) {
141 Display display
= Display
.getDefault();
142 if (!display
.isDisposed()) {
143 display
.syncExec(() -> {
144 deleteSeries(oldSeriesName
);
148 fSeriesName
.put(quark
, seriesName
);
151 Display
.getDefault().asyncExec(() -> {
157 * TODO: It should only show active threads in the time range.
158 * If a tid does not have any memory value (only 1 interval in
159 * the time range with value null or 0), then its series should
163 for (int i
= 0; i
< xvalues
.length
; i
++) {
164 if (monitor
.isCanceled()) {
167 double x
= xvalues
[i
];
168 long time
= (long) x
+ offset
;
169 // make sure that time is in the trace range after double to
171 time
= time
< traceStart ? traceStart
: time
;
172 time
= time
> traceEnd ? traceEnd
: time
;
174 fullState
= ss
.queryFullState(time
);
175 for (int quark
: tidQuarks
) {
176 double[] values
= checkNotNull(fYValues
.get(quark
));
178 Integer memQuark
= checkNotNull(fMemoryQuarks
.get(quark
));
179 yvalue
= fullState
.get(memQuark
.intValue()).getStateValue().unboxLong();
182 } catch (TimeRangeException e
) {
183 for (int quark
: tidQuarks
) {
184 double[] values
= checkNotNull(fYValues
.get(quark
));
189 for (int quark
: tidQuarks
) {
190 setSeries(fSeriesName
.get(quark
), fYValues
.get(quark
));
194 } catch (AttributeNotFoundException
| StateValueTypeException e
) {
195 Activator
.getDefault().logError("Error updating the data of the Memory usage view", e
); //$NON-NLS-1$
196 } catch (StateSystemDisposedException e
) {
197 /* State system is closing down, no point continuing */