Commit | Line | Data |
---|---|---|
aa19e48b NA |
1 | /********************************************************************** |
2 | * Copyright (c) 2016 École Polytechnique de Montréal | |
3 | * | |
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 | |
8 | **********************************************************************/ | |
9 | package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage; | |
10 | ||
aa19e48b NA |
11 | import java.util.List; |
12 | ||
13 | import org.eclipse.core.runtime.IProgressMonitor; | |
14 | import org.eclipse.swt.SWT; | |
15 | import org.eclipse.swt.widgets.Composite; | |
16 | import org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule; | |
f937c19c | 17 | import org.eclipse.tracecompass.common.core.format.DataSizeWithUnitFormat; |
aa19e48b NA |
18 | import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator; |
19 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | |
20 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
21 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; | |
22 | import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException; | |
23 | import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; | |
24 | import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; | |
25 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
26 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
27 | import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer; | |
28 | import org.swtchart.Chart; | |
29 | ||
30 | /** | |
31 | * Memory usage view | |
32 | * | |
33 | * @author Samuel Gagnon | |
34 | * @author Wassim Nasrallah | |
35 | */ | |
36 | public class KernelMemoryUsageViewer extends TmfCommonXLineChartViewer { | |
37 | ||
aa19e48b NA |
38 | private static final String NOT_SELECTED = "-1"; //$NON-NLS-1$ |
39 | ||
40 | private TmfStateSystemAnalysisModule fModule = null; | |
41 | private String fSelectedThread = NOT_SELECTED; | |
42 | ||
43 | /** | |
44 | * Constructor | |
45 | * | |
46 | * @param parent | |
47 | * parent view | |
48 | */ | |
49 | public KernelMemoryUsageViewer(Composite parent) { | |
50 | super(parent, Messages.MemoryUsageViewer_title, Messages.MemoryUsageViewer_xAxis, Messages.MemoryUsageViewer_yAxis); | |
51 | Chart chart = getSwtChart(); | |
c81aca6d | 52 | chart.getAxisSet().getYAxis(0).getTick().setFormat(DataSizeWithUnitFormat.getInstance()); |
aa19e48b NA |
53 | chart.getLegend().setPosition(SWT.BOTTOM); |
54 | } | |
55 | ||
56 | @Override | |
57 | protected void initializeDataSource() { | |
58 | ITmfTrace trace = getTrace(); | |
59 | if (trace != null) { | |
60 | fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, TmfStateSystemAnalysisModule.class, KernelMemoryAnalysisModule.ID); | |
61 | if (fModule == null) { | |
62 | return; | |
63 | } | |
64 | fModule.schedule(); | |
65 | } | |
66 | } | |
67 | ||
68 | @Override | |
69 | protected void updateData(long start, long end, int nb, IProgressMonitor monitor) { | |
70 | TmfStateSystemAnalysisModule module = fModule; | |
71 | if (getTrace() == null || module == null) { | |
72 | return; | |
73 | } | |
74 | ||
75 | if (!module.waitForInitialization()) { | |
76 | return; | |
77 | } | |
78 | ||
79 | ITmfStateSystem ss = module.getStateSystem(); | |
80 | if (ss == null) { | |
81 | throw new IllegalStateException(); | |
82 | } | |
83 | ||
84 | double[] xvalues = getXAxis(start, end, nb); | |
85 | if (xvalues.length == 0) { | |
86 | return; | |
87 | } | |
88 | setXAxis(xvalues); | |
89 | ||
90 | try { | |
91 | /** | |
92 | * For a given time range, we plot two lines representing the memory | |
93 | * allocation. The first line represent the total memory allocation | |
94 | * of every process. The second line represent the memory allocation | |
95 | * of the selected thread. | |
96 | */ | |
97 | double[] totalKernelMemoryValues = new double[xvalues.length]; | |
98 | double[] selectedThreadValues = new double[xvalues.length]; | |
99 | for (int i = 0; i < xvalues.length; i++) { | |
100 | if (monitor.isCanceled()) { | |
101 | return; | |
102 | } | |
103 | ||
104 | double x = xvalues[i]; | |
105 | long t = (long) x + getTimeOffset(); | |
106 | ||
107 | List<ITmfStateInterval> kernelState = ss.queryFullState(t); | |
108 | ||
109 | /* The subattributes of the root are the different threads */ | |
110 | List<Integer> threadQuarkList = ss.getSubAttributes(-1, false); | |
111 | /* We add the value of each thread to the total quantity */ | |
112 | for (Integer threadQuark : threadQuarkList) { | |
113 | ITmfStateInterval threadMemoryInterval = kernelState.get(threadQuark); | |
114 | long value = threadMemoryInterval.getStateValue().unboxLong(); | |
115 | totalKernelMemoryValues[i] += value; | |
116 | ||
117 | String tid = ss.getAttributeName(threadQuark); | |
118 | if (tid.equals(fSelectedThread)) { | |
119 | selectedThreadValues[i] = value; | |
120 | } | |
121 | } | |
122 | } | |
123 | ||
124 | /** | |
125 | * For each thread, we look for its lowest value since the beginning | |
126 | * of the trace. This way, we can avoid negative values in the plot. | |
127 | */ | |
128 | double totalKernelMemoryValuesShift = 0; | |
129 | double selectThreadValuesShift = 0; | |
130 | ||
131 | /* | |
132 | * The lowest value we are searching is at the end of the current | |
133 | * selected zone | |
134 | */ | |
135 | List<ITmfStateInterval> kernelState = ss.queryFullState(end); | |
136 | List<Integer> threadQuarkList = ss.getSubAttributes(-1, false); | |
137 | /* We add the lowest value of each thread */ | |
138 | for (Integer threadQuark : threadQuarkList) { | |
139 | int lowestMemoryQuark = ss.getQuarkRelative(threadQuark, KernelMemoryAnalysisModule.THREAD_LOWEST_MEMORY_VALUE); | |
140 | ITmfStateInterval lowestMemoryInterval = kernelState.get(lowestMemoryQuark); | |
141 | long lowestMemoryValue = lowestMemoryInterval.getStateValue().unboxLong(); | |
142 | // We want to add up a positive quantity. | |
143 | totalKernelMemoryValuesShift -= lowestMemoryValue; | |
144 | ||
145 | String tid = ss.getAttributeName(threadQuark); | |
146 | if (tid.equals(fSelectedThread)) { | |
147 | // We want to add up a positive quantity. | |
148 | selectThreadValuesShift = -lowestMemoryValue; | |
149 | } | |
150 | } | |
151 | ||
152 | /** | |
153 | * We shift the two displayed lines up. | |
154 | */ | |
155 | for (int i = 0; i < xvalues.length; i++) { | |
156 | totalKernelMemoryValues[i] += totalKernelMemoryValuesShift; | |
157 | selectedThreadValues[i] += selectThreadValuesShift; | |
158 | } | |
159 | setSeries(Messages.MemoryUsageViewer_Total, totalKernelMemoryValues); | |
160 | if (fSelectedThread != NOT_SELECTED) { | |
161 | setSeries(fSelectedThread, selectedThreadValues); | |
162 | } | |
163 | updateDisplay(); | |
164 | ||
165 | } catch (TimeRangeException | StateSystemDisposedException | AttributeNotFoundException e) { | |
166 | Activator.getDefault().logError(e.getMessage(), e); | |
167 | } | |
168 | } | |
169 | ||
170 | /** | |
171 | * Set the selected thread ID, which will be graphed in this viewer | |
172 | * | |
173 | * @param tid | |
174 | * The selected thread ID | |
175 | */ | |
176 | public void setSelectedThread(String tid) { | |
177 | cancelUpdate(); | |
178 | deleteSeries(fSelectedThread); | |
179 | fSelectedThread = tid; | |
180 | updateContent(); | |
181 | } | |
182 | ||
183 | } |