d38cc423a72fd18ec16411bff00959b161467d78
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / analysis / os / linux / core / contextswitch / KernelContextSwitchAnalysis.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
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 * Alexis Cabana-Loriaux - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.analysis.os.linux.core.contextswitch;
14
15 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
16
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23
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.IKernelAnalysisEventLayout;
30 import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
31 import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
32 import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
33 import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
34 import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
35 import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
36 import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
37 import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
38 import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
39 import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
40 import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
41 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
42 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
43
44 /**
45 * This analysis module computes the number of context switches of a system from
46 * a kernel trace.
47 *
48 * @author Alexis Cabana-Loriaux
49 * @since 2.0
50 */
51 @NonNullByDefault
52 public class KernelContextSwitchAnalysis extends TmfStateSystemAnalysisModule {
53
54 /** The ID of this analysis */
55 public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.contextswitch"; //$NON-NLS-1$
56
57 /** Integer used to identify 'total' entries in the returned maps */
58 public static final Integer TOTAL = -1;
59
60 @Override
61 protected ITmfStateProvider createStateProvider() {
62 ITmfTrace trace = checkNotNull(getTrace());
63 IKernelAnalysisEventLayout layout;
64
65 if (trace instanceof IKernelTrace) {
66 layout = ((IKernelTrace) trace).getKernelEventLayout();
67 } else {
68 /* Fall-back to the base LttngEventLayout */
69 layout = IKernelAnalysisEventLayout.DEFAULT_LAYOUT;
70 }
71
72 return new KernelContextSwitchStateProvider(trace, layout);
73 }
74
75 @Override
76 protected StateSystemBackendType getBackendType() {
77 return StateSystemBackendType.FULL;
78 }
79
80 @Override
81 protected Iterable<IAnalysisModule> getDependentAnalyses() {
82 Set<IAnalysisModule> modules = new HashSet<>();
83
84 ITmfTrace trace = getTrace();
85 if (trace == null) {
86 throw new IllegalStateException();
87 }
88 /*
89 * This analysis depends on the LTTng kernel analysis, so it's added to
90 * dependent modules.
91 */
92 Iterable<KernelAnalysisModule> kernelModules = TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class);
93 for (KernelAnalysisModule kernelModule : kernelModules) {
94 /* Only add the first one we find, if there is one */
95 modules.add(kernelModule);
96 break;
97 }
98 return modules;
99 }
100
101 /**
102 * Get a map of the number of context switch per CPU during a time range.
103 *
104 * @param startParam
105 * Start time of requested range
106 * @param endParam
107 * End time of requested range
108 * @return A map of CPU# -> nb of context switch in the [start, end]
109 * interval. CPU# == -1 represents the total number of context
110 * switch
111 * @throws TimeRangeException
112 * if one or more of the parameters is outside the range the
113 * state history
114 */
115 public @NonNullByDefault({}) @NonNull Map<Integer, Long> getContextSwitchesRange(final long startParam, final long endParam) {
116 final @Nullable ITmfStateSystem stateSystem = getStateSystem();
117 ITmfTrace trace = getTrace();
118 if (trace == null || stateSystem == null) {
119 return Collections.<Integer, Long> emptyMap();
120 }
121 long start = Math.max(startParam, stateSystem.getStartTime());
122 long end = Math.min(endParam, stateSystem.getCurrentEndTime());
123 ITmfStateSystem contextSwitchStateSystem = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelContextSwitchAnalysis.ID);
124 if (contextSwitchStateSystem == null) {
125 return Collections.<Integer, Long> emptyMap();
126 }
127
128 /*
129 * Make sure the start/end times are within the state history, so we
130 * don't get TimeRange exceptions.
131 */
132 long startTime = contextSwitchStateSystem.getStartTime();
133 long endTime = contextSwitchStateSystem.getCurrentEndTime();
134 if (endTime < startTime) {
135 return Collections.<Integer, Long> emptyMap();
136 }
137
138 Map<Integer, Long> map = new HashMap<>();
139 try {
140 /* Get the list of quarks for each CPU */
141 int cpusNode = contextSwitchStateSystem.getQuarkAbsolute(Attributes.CPUS);
142 List<Integer> cpuQuarks = contextSwitchStateSystem.getSubAttributes(cpusNode, false);
143 /* Query full states at start and end times */
144 List<ITmfStateInterval> kernelEndState = contextSwitchStateSystem.queryFullState(end);
145 List<ITmfStateInterval> kernelStartState = contextSwitchStateSystem.queryFullState(start);
146 Long totalNbCxtSwt = 0l;
147 for (Integer cpuQuark : cpuQuarks) {
148 int cpuNb = Integer.parseInt(contextSwitchStateSystem.getAttributeName(cpuQuark.intValue()));
149 Long nbCxtSwtForCore = kernelEndState.get(cpuQuark).getStateValue().unboxLong() - kernelStartState.get(cpuQuark).getStateValue().unboxLong();
150 map.put(cpuNb, nbCxtSwtForCore);
151 totalNbCxtSwt += nbCxtSwtForCore;
152 }
153
154 /* Put the total number of context switches in the interval */
155 map.put(TOTAL, totalNbCxtSwt);
156 } catch (TimeRangeException | AttributeNotFoundException e) {
157 /*
158 * Assume there is no events or the attribute does not exist yet,
159 * nothing will be put in the map.
160 */
161 } catch (StateValueTypeException | StateSystemDisposedException e) {
162 /*
163 * These other exception types would show a logic problem, so they
164 * should not happen.
165 */
166 Activator.getDefault().logError("Error getting CPU context switches in a time range", e); //$NON-NLS-1$
167 }
168
169 return map;
170 }
171
172 }
This page took 0.047781 seconds and 4 git commands to generate.