Copyright header update, 2015 edition
[deliverable/tracecompass.git] / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / analysis / os / linux / core / cpuusage / KernelCpuUsageStateProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 É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 * François Rajotte - Initial API and implementation
11 * Geneviève Bastien - Revision of the initial implementation
12 *******************************************************************************/
13
14 package org.eclipse.tracecompass.analysis.os.linux.core.cpuusage;
15
16 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
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;
35
36 /**
37 * Creates a state system with the total time spent on CPU for each thread and
38 * for each CPU from a kernel trace.
39 *
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.
44 *
45 * It requires only the 'sched_switch' events enabled on the trace.
46 *
47 * @author François Rajotte
48 */
49 public class KernelCpuUsageStateProvider extends AbstractTmfStateProvider {
50
51 private static final int VERSION = 2;
52
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;
57
58 /**
59 * Constructor
60 *
61 * @param trace
62 * The trace from which to get the CPU usage
63 * @param layout
64 * The event layout to use for this state provider.
65 */
66 public KernelCpuUsageStateProvider(ITmfTrace trace, IKernelAnalysisEventLayout layout) {
67 super(trace, ITmfEvent.class, "Kernel CPU usage"); //$NON-NLS-1$
68 fTraceStart = trace.getStartTime().getValue();
69 fLayout = layout;
70 }
71
72 // ------------------------------------------------------------------------
73 // ITmfStateProvider
74 // ------------------------------------------------------------------------
75
76 @Override
77 public int getVersion() {
78 return VERSION;
79 }
80
81 @Override
82 public KernelCpuUsageStateProvider getNewInstance() {
83 return new KernelCpuUsageStateProvider(this.getTrace(), this.fLayout);
84 }
85
86 @Override
87 protected void eventHandle(@Nullable ITmfEvent event) {
88 if (event == null) {
89 return;
90 }
91 final String eventName = event.getType().getName();
92
93 if (eventName.equals(fLayout.eventSchedSwitch())) {
94 Integer cpu = null;
95 Iterable<TmfCpuAspect> aspects = TmfTraceUtils.getEventAspectsOfClass(event.getTrace(), TmfCpuAspect.class);
96 for (TmfCpuAspect aspect : aspects) {
97 cpu = aspect.resolve(event);
98 if (cpu != null) {
99 break;
100 }
101 }
102 if (cpu == null) {
103 /* We couldn't find any CPU information, ignore this event */
104 return;
105 }
106
107 /*
108 * Fields: string prev_comm, int32 prev_tid, int32 prev_prio, int64
109 * prev_state, string next_comm, int32 next_tid, int32 next_prio
110 */
111 ITmfEventField content = event.getContent();
112 long ts = event.getTimestamp().getValue();
113
114 Long prevTid = (Long) content.getField(fLayout.fieldPrevTid()).getValue();
115
116 try {
117 final ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
118
119 Integer currentCPUNode = ss.getQuarkRelativeAndAdd(getNodeCPUs(ss), cpu.toString());
120
121 /*
122 * This quark contains the value of the cumulative time spent on
123 * the source CPU by the currently running thread
124 */
125 Integer cumulativeTimeQuark = ss.getQuarkRelativeAndAdd(currentCPUNode, prevTid.toString());
126 Long startTime = fLastStartTimes.get(cpu);
127 /*
128 * If start time is null, we haven't seen the start of the
129 * process, so we assume beginning of the trace
130 */
131 if (startTime == null) {
132 startTime = fTraceStart;
133 }
134
135 /*
136 * We add the time from startTime until now to the cumulative
137 * time of the thread
138 */
139 if (startTime != null) {
140 ITmfStateValue value = ss.queryOngoingState(cumulativeTimeQuark);
141
142 /*
143 * Modify cumulative time for this CPU/TID combo: The total
144 * time changes when the process is scheduled out. Nothing
145 * happens when the process is scheduled in.
146 */
147 long prevCumulativeTime = Math.max(0, value.unboxLong());
148 long newCumulativeTime = prevCumulativeTime + (ts - startTime);
149
150 value = TmfStateValue.newValueLong(newCumulativeTime);
151 ss.modifyAttribute(ts, value, cumulativeTimeQuark);
152 fLastStartTimes.put(cpu, ts);
153 }
154 } catch (AttributeNotFoundException e) {
155 Activator.getDefault().logError("Attribute not found in LttngKernelCpuStateProvider", e); //$NON-NLS-1$
156 }
157
158 }
159 }
160
161 /* Shortcut for the "current CPU" attribute node */
162 private static int getNodeCPUs(ITmfStateSystemBuilder ssb) {
163 return ssb.getQuarkAbsoluteAndAdd(Attributes.CPUS);
164 }
165
166 }
This page took 0.033603 seconds and 5 git commands to generate.