1 /*******************************************************************************
2 * Copyright (c) 2014 É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 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.internal
.lttng2
.kernel
.ui
.views
.cpuusage
;
15 import java
.util
.ArrayList
;
16 import java
.util
.HashMap
;
17 import java
.util
.List
;
19 import java
.util
.Map
.Entry
;
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
.statesystem
.core
.ITmfStateSystem
;
27 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
28 import org
.eclipse
.linuxtools
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
29 import org
.eclipse
.linuxtools
.statesystem
.core
.interval
.ITmfStateInterval
;
30 import org
.eclipse
.linuxtools
.statesystem
.core
.statevalue
.ITmfStateValue
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.statesystem
.TmfStateSystemAnalysisModule
;
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
;
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.
46 * @author Geneviève Bastien
48 public class CpuUsageComposite
extends AbstractTmfTreeViewer
{
50 private LttngKernelCpuUsageAnalysis fModule
= null;
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
59 /* A map that saves the mapping of a thread ID to its executable name */
60 private final Map
<String
, String
> fProcessNameMap
= new HashMap
<>();
62 /** Provides label for the CPU usage tree viewer cells */
63 protected static class CpuLabelProvider
extends TreeLabelProvider
{
66 public String
getColumnText(Object element
, int columnIndex
) {
67 CpuUsageEntry obj
= (CpuUsageEntry
) element
;
68 if (columnIndex
== 0) {
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());
78 return element
.toString();
87 * The parent composite that holds this viewer
89 public CpuUsageComposite(Composite parent
) {
91 setLabelProvider(new CpuLabelProvider());
95 protected ITmfTreeColumnDataProvider
getColumnDataProvider() {
96 return new ITmfTreeColumnDataProvider() {
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() {
105 public int compare(Viewer viewer
, Object e1
, Object e2
) {
106 CpuUsageEntry n1
= (CpuUsageEntry
) e1
;
107 CpuUsageEntry n2
= (CpuUsageEntry
) e2
;
109 return n1
.getTid().compareTo(n2
.getTid());
114 column
= new TmfTreeColumnData(COLUMN_NAMES
[1]);
115 column
.setComparator(new ViewerComparator() {
117 public int compare(Viewer viewer
, Object e1
, Object e2
) {
118 CpuUsageEntry n1
= (CpuUsageEntry
) e1
;
119 CpuUsageEntry n2
= (CpuUsageEntry
) e2
;
121 return n1
.getProcessName().compareTo(n2
.getProcessName());
126 column
= new TmfTreeColumnData(COLUMN_NAMES
[2]);
127 column
.setComparator(new ViewerComparator() {
129 public int compare(Viewer viewer
, Object e1
, Object e2
) {
130 CpuUsageEntry n1
= (CpuUsageEntry
) e1
;
131 CpuUsageEntry n2
= (CpuUsageEntry
) e2
;
133 return n1
.getPercent().compareTo(n2
.getPercent());
137 column
.setPercentageProvider(new ITmfColumnPercentageProvider() {
140 public double getPercentage(Object data
) {
141 CpuUsageEntry parent
= (CpuUsageEntry
) data
;
142 return parent
.getPercent() / 100;
146 column
= new TmfTreeColumnData(COLUMN_NAMES
[3]);
147 column
.setComparator(new ViewerComparator() {
149 public int compare(Viewer viewer
, Object e1
, Object e2
) {
150 CpuUsageEntry n1
= (CpuUsageEntry
) e1
;
151 CpuUsageEntry n2
= (CpuUsageEntry
) e2
;
153 return n1
.getTime().compareTo(n2
.getTime());
165 // ------------------------------------------------------------------------
167 // ------------------------------------------------------------------------
170 public void initializeDataSource() {
171 fModule
= getTrace().getAnalysisModuleOfClass(LttngKernelCpuUsageAnalysis
.class, LttngKernelCpuUsageAnalysis
.ID
);
172 if (fModule
== null) {
176 fModule
.waitForInitialization();
177 fProcessNameMap
.clear();
181 protected ITmfTreeViewerEntry
updateElements(long start
, long end
, boolean isSelection
) {
182 if (isSelection
|| (start
== end
)) {
185 if (getTrace() == null || fModule
== null) {
188 ITmfStateSystem ss
= fModule
.getStateSystem();
189 /* Don't wait for the module completion, when it's ready, we'll know */
194 /* Initialize the data */
195 Map
<String
, Long
> cpuUsageMap
= fModule
.getCpuUsageInRange(Math
.max(start
, getStartTime()), Math
.min(end
, getEndTime()));
197 TmfTreeViewerEntry root
= new TmfTreeViewerEntry(""); //$NON-NLS-1$
198 List
<ITmfTreeViewerEntry
> entryList
= root
.getChildren();
200 for (Entry
<String
, Long
> entry
: cpuUsageMap
.entrySet()) {
202 * Process only entries representing the total of all CPUs and that
205 if (entry
.getValue() == 0) {
208 if (!entry
.getKey().startsWith(LttngKernelCpuUsageAnalysis
.TOTAL
)) {
211 String
[] strings
= entry
.getKey().split(LttngKernelCpuUsageAnalysis
.SPLIT_STRING
, 2);
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());
223 * Get the process name from its TID by using the LTTng kernel analysis
226 private String
getProcessName(String tid
) {
227 String execName
= fProcessNameMap
.get(tid
);
228 if (execName
!= null) {
231 TmfStateSystemAnalysisModule module
= getTrace().getAnalysisModuleOfClass(TmfStateSystemAnalysisModule
.class, LttngKernelAnalysisModule
.ID
);
232 if (module
== null) {
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.
240 ITmfStateSystem kernelSs
= module
.getStateSystem();
241 if (kernelSs
== null) {
246 int cpusNode
= kernelSs
.getQuarkAbsolute(Attributes
.THREADS
);
248 /* Get the quarks for each cpu */
249 List
<Integer
> cpuNodes
= kernelSs
.getSubAttributes(cpusNode
, false);
251 for (Integer tidQuark
: cpuNodes
) {
252 if (kernelSs
.getAttributeName(tidQuark
).equals(tid
)) {
254 List
<ITmfStateInterval
> execNameIntervals
;
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 */
261 } catch (StateSystemDisposedException e
) {
262 /* State system is closing down, no point continuing */
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
);
277 } catch (AttributeNotFoundException e
) {
278 /* can't find the process name, just return the tid instead */