1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
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 * Alexis Cabana-Loriaux - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.contextswitch
;
15 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
17 import java
.util
.Collections
;
18 import java
.util
.HashMap
;
19 import java
.util
.HashSet
;
20 import java
.util
.List
;
24 import org
.eclipse
.jdt
.annotation
.NonNull
;
25 import org
.eclipse
.jdt
.annotation
.NonNullByDefault
;
26 import org
.eclipse
.jdt
.annotation
.Nullable
;
27 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.Attributes
;
28 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.kernel
.KernelAnalysisModule
;
29 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.DefaultEventLayout
;
30 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelAnalysisEventLayout
;
31 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.trace
.IKernelTrace
;
32 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.Activator
;
33 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
34 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
35 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
36 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateValueTypeException
;
37 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.TimeRangeException
;
38 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.analysis
.IAnalysisModule
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.ITmfStateProvider
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.statesystem
.TmfStateSystemAnalysisModule
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceUtils
;
46 * This analysis module computes the number of context switches of a system from
49 * @author Alexis Cabana-Loriaux
53 public class KernelContextSwitchAnalysis
extends TmfStateSystemAnalysisModule
{
55 /** The ID of this analysis */
56 public static final String ID
= "org.eclipse.tracecompass.analysis.os.linux.contextswitch"; //$NON-NLS-1$
58 /** Integer used to identify 'total' entries in the returned maps */
59 public static final Integer TOTAL
= -1;
62 protected ITmfStateProvider
createStateProvider() {
63 ITmfTrace trace
= checkNotNull(getTrace());
64 IKernelAnalysisEventLayout layout
;
66 if (trace
instanceof IKernelTrace
) {
67 layout
= ((IKernelTrace
) trace
).getKernelEventLayout();
69 /* Fall-back to the base LttngEventLayout */
70 layout
= DefaultEventLayout
.getInstance();
73 return new KernelContextSwitchStateProvider(trace
, layout
);
77 protected StateSystemBackendType
getBackendType() {
78 return StateSystemBackendType
.FULL
;
82 protected Iterable
<IAnalysisModule
> getDependentAnalyses() {
83 Set
<IAnalysisModule
> modules
= new HashSet
<>();
85 ITmfTrace trace
= getTrace();
87 throw new IllegalStateException();
90 * This analysis depends on the LTTng kernel analysis, so it's added to
93 Iterable
<KernelAnalysisModule
> kernelModules
= TmfTraceUtils
.getAnalysisModulesOfClass(trace
, KernelAnalysisModule
.class);
94 for (KernelAnalysisModule kernelModule
: kernelModules
) {
95 /* Only add the first one we find, if there is one */
96 modules
.add(kernelModule
);
103 * Get a map of the number of context switch per CPU during a time range.
106 * Start time of requested range
108 * End time of requested range
109 * @return A map of CPU# -> nb of context switch in the [start, end]
110 * interval. CPU# == -1 represents the total number of context
112 * @throws TimeRangeException
113 * if one or more of the parameters is outside the range the
116 public @NonNullByDefault({}) @NonNull Map
<Integer
, Long
> getContextSwitchesRange(final long startParam
, final long endParam
) {
117 final @Nullable ITmfStateSystem stateSystem
= getStateSystem();
118 ITmfTrace trace
= getTrace();
119 if (trace
== null || stateSystem
== null) {
120 return Collections
.<Integer
, Long
> emptyMap();
122 long start
= Math
.max(startParam
, stateSystem
.getStartTime());
123 long end
= Math
.min(endParam
, stateSystem
.getCurrentEndTime());
124 ITmfStateSystem contextSwitchStateSystem
= TmfStateSystemAnalysisModule
.getStateSystem(trace
, KernelContextSwitchAnalysis
.ID
);
125 if (contextSwitchStateSystem
== null) {
126 return Collections
.<Integer
, Long
> emptyMap();
130 * Make sure the start/end times are within the state history, so we
131 * don't get TimeRange exceptions.
133 long startTime
= contextSwitchStateSystem
.getStartTime();
134 long endTime
= contextSwitchStateSystem
.getCurrentEndTime();
135 if (endTime
< startTime
) {
136 return Collections
.<Integer
, Long
> emptyMap();
139 Map
<Integer
, Long
> map
= new HashMap
<>();
141 /* Get the list of quarks for each CPU */
142 int cpusNode
= contextSwitchStateSystem
.getQuarkAbsolute(Attributes
.CPUS
);
143 List
<Integer
> cpuQuarks
= contextSwitchStateSystem
.getSubAttributes(cpusNode
, false);
144 /* Query full states at start and end times */
145 List
<ITmfStateInterval
> kernelEndState
= contextSwitchStateSystem
.queryFullState(end
);
146 List
<ITmfStateInterval
> kernelStartState
= contextSwitchStateSystem
.queryFullState(start
);
147 Long totalNbCxtSwt
= 0l;
148 for (Integer cpuQuark
: cpuQuarks
) {
149 int cpuNb
= Integer
.parseInt(contextSwitchStateSystem
.getAttributeName(cpuQuark
.intValue()));
150 Long nbCxtSwtForCore
= kernelEndState
.get(cpuQuark
).getStateValue().unboxLong() - kernelStartState
.get(cpuQuark
).getStateValue().unboxLong();
151 map
.put(cpuNb
, nbCxtSwtForCore
);
152 totalNbCxtSwt
+= nbCxtSwtForCore
;
155 /* Put the total number of context switches in the interval */
156 map
.put(TOTAL
, totalNbCxtSwt
);
157 } catch (TimeRangeException
| AttributeNotFoundException e
) {
159 * Assume there is no events or the attribute does not exist yet,
160 * nothing will be put in the map.
162 } catch (StateValueTypeException
| StateSystemDisposedException e
) {
164 * These other exception types would show a logic problem, so they
167 Activator
.getDefault().logError("Error getting CPU context switches in a time range", e
); //$NON-NLS-1$