1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 É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 * François Rajotte - Initial API and implementation
11 * Geneviève Bastien - Revision of the initial implementation
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.cpuusage
;
16 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
18 import java
.util
.HashMap
;
21 import org
.eclipse
.jdt
.annotation
.Nullable
;
22 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernelanalysis
.Attributes
;
23 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelAnalysisEventLayout
;
24 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.Activator
;
25 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystemBuilder
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.ITmfStateValue
;
28 import org
.eclipse
.tracecompass
.statesystem
.core
.statevalue
.TmfStateValue
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.TmfCpuAspect
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.AbstractTmfStateProvider
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
37 * Creates a state system with the total time spent on CPU for each thread and
38 * for each CPU from a kernel trace.
40 * This state system in itself keeps the total time on CPU since last time the
41 * process was scheduled out. The state system queries will only be accurate
42 * when the process is not in a running state. To have exact CPU usage when
43 * running, this state system needs to be used along the LTTng Kernel analysis.
45 * It requires only the 'sched_switch' events enabled on the trace.
47 * @author François Rajotte
49 public class KernelCpuUsageStateProvider
extends AbstractTmfStateProvider
{
51 private static final int VERSION
= 2;
53 /* For each CPU, maps the last time a thread was scheduled in */
54 private final Map
<Integer
, Long
> fLastStartTimes
= new HashMap
<>();
55 private final long fTraceStart
;
56 private final IKernelAnalysisEventLayout fLayout
;
62 * The trace from which to get the CPU usage
64 * The event layout to use for this state provider.
66 public KernelCpuUsageStateProvider(ITmfTrace trace
, IKernelAnalysisEventLayout layout
) {
67 super(trace
, "Kernel CPU usage"); //$NON-NLS-1$
68 fTraceStart
= trace
.getStartTime().getValue();
72 // ------------------------------------------------------------------------
74 // ------------------------------------------------------------------------
77 public int getVersion() {
82 public KernelCpuUsageStateProvider
getNewInstance() {
83 return new KernelCpuUsageStateProvider(this.getTrace(), this.fLayout
);
87 protected void eventHandle(@Nullable ITmfEvent event
) {
91 final String eventName
= event
.getName();
93 if (eventName
.equals(fLayout
.eventSchedSwitch())) {
94 Object cpuObj
= TmfTraceUtils
.resolveEventAspectOfClassForEvent(event
.getTrace(), TmfCpuAspect
.class, event
);
96 /* We couldn't find any CPU information, ignore this event */
99 Integer cpu
= (Integer
) cpuObj
;
102 * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, int64
103 * prev_state, string next_comm, int32 next_tid, int32 next_prio
105 ITmfEventField content
= event
.getContent();
106 long ts
= event
.getTimestamp().getValue();
108 Long prevTid
= (Long
) content
.getField(fLayout
.fieldPrevTid()).getValue();
111 final ITmfStateSystemBuilder ss
= checkNotNull(getStateSystemBuilder());
113 Integer currentCPUNode
= ss
.getQuarkRelativeAndAdd(getNodeCPUs(ss
), cpu
.toString());
116 * This quark contains the value of the cumulative time spent on
117 * the source CPU by the currently running thread
119 Integer cumulativeTimeQuark
= ss
.getQuarkRelativeAndAdd(currentCPUNode
, prevTid
.toString());
120 Long startTime
= fLastStartTimes
.get(cpu
);
122 * If start time is null, we haven't seen the start of the
123 * process, so we assume beginning of the trace
125 if (startTime
== null) {
126 startTime
= fTraceStart
;
130 * We add the time from startTime until now to the cumulative
133 ITmfStateValue value
= ss
.queryOngoingState(cumulativeTimeQuark
);
136 * Modify cumulative time for this CPU/TID combo: The total time
137 * changes when the process is scheduled out. Nothing happens
138 * when the process is scheduled in.
140 long prevCumulativeTime
= Math
.max(0, value
.unboxLong());
141 long newCumulativeTime
= prevCumulativeTime
+ (ts
- startTime
);
143 value
= TmfStateValue
.newValueLong(newCumulativeTime
);
144 ss
.modifyAttribute(ts
, value
, cumulativeTimeQuark
);
145 fLastStartTimes
.put(cpu
, ts
);
147 } catch (AttributeNotFoundException e
) {
148 Activator
.getDefault().logError("Attribute not found in LttngKernelCpuStateProvider", e
); //$NON-NLS-1$
154 /* Shortcut for the "current CPU" attribute node */
155 private static int getNodeCPUs(ITmfStateSystemBuilder ssb
) {
156 return ssb
.getQuarkAbsoluteAndAdd(Attributes
.CPUS
);