27c88ef39f63438d67f1906d2d7a177c8b908826
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / cpuusage / CpuUsageComposite.java
1 /*******************************************************************************
2 * Copyright (c) 2014 É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 * Contributors:
10 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.cpuusage;
14
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Map.Entry;
20
21 import org.eclipse.jface.viewers.Viewer;
22 import org.eclipse.jface.viewers.ViewerComparator;
23 import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
24 import org.eclipse.linuxtools.lttng2.kernel.core.analysis.LttngKernelAnalysisModule;
25 import org.eclipse.linuxtools.lttng2.kernel.core.cpuusage.LttngKernelCpuUsageAnalysis;
26 import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
27 import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
28 import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
29 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
30 import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule;
31 import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
32 import org.eclipse.linuxtools.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
33 import org.eclipse.linuxtools.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
34 import org.eclipse.linuxtools.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
35 import org.eclipse.linuxtools.tmf.ui.viewers.tree.TmfTreeColumnData;
36 import org.eclipse.linuxtools.tmf.ui.viewers.tree.TmfTreeColumnData.ITmfColumnPercentageProvider;
37 import org.eclipse.linuxtools.tmf.ui.viewers.tree.TmfTreeViewerEntry;
38 import org.eclipse.osgi.util.NLS;
39 import org.eclipse.swt.widgets.Composite;
40
41 /**
42 * Tree viewer to display CPU usage information in a specified time range. It
43 * shows the process's TID, its name, the time spent on the CPU during that
44 * range, in % and absolute value.
45 *
46 * @author Geneviève Bastien
47 */
48 public class CpuUsageComposite extends AbstractTmfTreeViewer {
49
50 private LttngKernelCpuUsageAnalysis fModule = null;
51
52 private static final String[] COLUMN_NAMES = new String[] {
53 Messages.CpuUsageComposite_ColumnTID,
54 Messages.CpuUsageComposite_ColumnProcess,
55 Messages.CpuUsageComposite_ColumnPercent,
56 Messages.CpuUsageComposite_ColumnTime
57 };
58
59 /* A map that saves the mapping of a thread ID to its executable name */
60 private final Map<String, String> fProcessNameMap = new HashMap<>();
61
62 /** Provides label for the CPU usage tree viewer cells */
63 protected static class CpuLabelProvider extends TreeLabelProvider {
64
65 @Override
66 public String getColumnText(Object element, int columnIndex) {
67 CpuUsageEntry obj = (CpuUsageEntry) element;
68 if (columnIndex == 0) {
69 return obj.getTid();
70 } else if (columnIndex == 1) {
71 return obj.getProcessName();
72 } else if (columnIndex == 2) {
73 return String.format(Messages.CpuUsageComposite_TextPercent, obj.getPercent());
74 } else if (columnIndex == 3) {
75 return NLS.bind(Messages.CpuUsageComposite_TextTime, obj.getTime());
76 }
77
78 return element.toString();
79 }
80
81 }
82
83 /**
84 * Constructor
85 *
86 * @param parent
87 * The parent composite that holds this viewer
88 */
89 public CpuUsageComposite(Composite parent) {
90 super(parent, false);
91 setLabelProvider(new CpuLabelProvider());
92 }
93
94 @Override
95 protected ITmfTreeColumnDataProvider getColumnDataProvider() {
96 return new ITmfTreeColumnDataProvider() {
97
98 @Override
99 public List<TmfTreeColumnData> getColumnData() {
100 /* All columns are sortable */
101 List<TmfTreeColumnData> columns = new ArrayList<>();
102 TmfTreeColumnData column = new TmfTreeColumnData(COLUMN_NAMES[0]);
103 column.setComparator(new ViewerComparator() {
104 @Override
105 public int compare(Viewer viewer, Object e1, Object e2) {
106 CpuUsageEntry n1 = (CpuUsageEntry) e1;
107 CpuUsageEntry n2 = (CpuUsageEntry) e2;
108
109 return n1.getTid().compareTo(n2.getTid());
110
111 }
112 });
113 columns.add(column);
114 column = new TmfTreeColumnData(COLUMN_NAMES[1]);
115 column.setComparator(new ViewerComparator() {
116 @Override
117 public int compare(Viewer viewer, Object e1, Object e2) {
118 CpuUsageEntry n1 = (CpuUsageEntry) e1;
119 CpuUsageEntry n2 = (CpuUsageEntry) e2;
120
121 return n1.getProcessName().compareTo(n2.getProcessName());
122
123 }
124 });
125 columns.add(column);
126 column = new TmfTreeColumnData(COLUMN_NAMES[2]);
127 column.setComparator(new ViewerComparator() {
128 @Override
129 public int compare(Viewer viewer, Object e1, Object e2) {
130 CpuUsageEntry n1 = (CpuUsageEntry) e1;
131 CpuUsageEntry n2 = (CpuUsageEntry) e2;
132
133 return n1.getPercent().compareTo(n2.getPercent());
134
135 }
136 });
137 column.setPercentageProvider(new ITmfColumnPercentageProvider() {
138
139 @Override
140 public double getPercentage(Object data) {
141 CpuUsageEntry parent = (CpuUsageEntry) data;
142 return parent.getPercent() / 100;
143 }
144 });
145 columns.add(column);
146 column = new TmfTreeColumnData(COLUMN_NAMES[3]);
147 column.setComparator(new ViewerComparator() {
148 @Override
149 public int compare(Viewer viewer, Object e1, Object e2) {
150 CpuUsageEntry n1 = (CpuUsageEntry) e1;
151 CpuUsageEntry n2 = (CpuUsageEntry) e2;
152
153 return n1.getTime().compareTo(n2.getTime());
154
155 }
156 });
157 columns.add(column);
158
159 return columns;
160 }
161
162 };
163 }
164
165 // ------------------------------------------------------------------------
166 // Operations
167 // ------------------------------------------------------------------------
168
169 @Override
170 public void initializeDataSource() {
171 fModule = getTrace().getAnalysisModuleOfClass(LttngKernelCpuUsageAnalysis.class, LttngKernelCpuUsageAnalysis.ID);
172 if (fModule == null) {
173 return;
174 }
175 fModule.schedule();
176 fModule.waitForInitialization();
177 fProcessNameMap.clear();
178 }
179
180 @Override
181 protected ITmfTreeViewerEntry updateElements(long start, long end, boolean isSelection) {
182 if (isSelection || (start == end)) {
183 return null;
184 }
185 if (getTrace() == null || fModule == null) {
186 return null;
187 }
188 ITmfStateSystem ss = fModule.getStateSystem();
189 /* Don't wait for the module completion, when it's ready, we'll know */
190 if (ss == null) {
191 return null;
192 }
193
194 /* Initialize the data */
195 Map<String, Long> cpuUsageMap = fModule.getCpuUsageInRange(Math.max(start, getStartTime()), Math.min(end, getEndTime()));
196
197 TmfTreeViewerEntry root = new TmfTreeViewerEntry(""); //$NON-NLS-1$
198 List<ITmfTreeViewerEntry> entryList = root.getChildren();
199
200 for (Entry<String, Long> entry : cpuUsageMap.entrySet()) {
201 /*
202 * Process only entries representing the total of all CPUs and that
203 * have time on CPU
204 */
205 if (entry.getValue() == 0) {
206 continue;
207 }
208 if (!entry.getKey().startsWith(LttngKernelCpuUsageAnalysis.TOTAL)) {
209 continue;
210 }
211 String[] strings = entry.getKey().split(LttngKernelCpuUsageAnalysis.SPLIT_STRING, 2);
212
213 if ((strings.length > 1) && !(strings[1].equals(LttngKernelCpuUsageAnalysis.TID_ZERO))) {
214 CpuUsageEntry obj = new CpuUsageEntry(strings[1], getProcessName(strings[1]), (double) entry.getValue() / (double) (end - start) * 100, entry.getValue());
215 entryList.add(obj);
216 }
217 }
218
219 return root;
220 }
221
222 /*
223 * Get the process name from its TID by using the LTTng kernel analysis
224 * module
225 */
226 private String getProcessName(String tid) {
227 String execName = fProcessNameMap.get(tid);
228 if (execName != null) {
229 return execName;
230 }
231 TmfStateSystemAnalysisModule module = getTrace().getAnalysisModuleOfClass(TmfStateSystemAnalysisModule.class, LttngKernelAnalysisModule.ID);
232 if (module == null) {
233 return tid;
234 }
235 /*
236 * Do not schedule the analysis here. It should have been executed when
237 * the CPU usage analysis was executed. If it's not available, there
238 * might be a good reason (disk space?) so don't force it.
239 */
240 ITmfStateSystem kernelSs = module.getStateSystem();
241 if (kernelSs == null) {
242 return tid;
243 }
244
245 try {
246 int cpusNode = kernelSs.getQuarkAbsolute(Attributes.THREADS);
247
248 /* Get the quarks for each cpu */
249 List<Integer> cpuNodes = kernelSs.getSubAttributes(cpusNode, false);
250
251 for (Integer tidQuark : cpuNodes) {
252 if (kernelSs.getAttributeName(tidQuark).equals(tid)) {
253 int execNameQuark;
254 List<ITmfStateInterval> execNameIntervals;
255 try {
256 execNameQuark = kernelSs.getQuarkRelative(tidQuark, Attributes.EXEC_NAME);
257 execNameIntervals = kernelSs.queryHistoryRange(execNameQuark, getStartTime(), getEndTime());
258 } catch (AttributeNotFoundException e) {
259 /* No information on this thread (yet?), skip it for now */
260 continue;
261 } catch (StateSystemDisposedException e) {
262 /* State system is closing down, no point continuing */
263 break;
264 }
265
266 for (ITmfStateInterval execNameInterval : execNameIntervals) {
267 if (!execNameInterval.getStateValue().isNull() &&
268 execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
269 execName = execNameInterval.getStateValue().unboxStr();
270 fProcessNameMap.put(tid, execName);
271 return execName;
272 }
273 }
274 }
275 }
276
277 } catch (AttributeNotFoundException e) {
278 /* can't find the process name, just return the tid instead */
279 }
280 return tid;
281 }
282
283 }
This page took 0.05501 seconds and 4 git commands to generate.