CPU Usage view
View the cpu usage on a per process basis
Change-Id: Ibe89e8aecf5439e4edabb0aa844c5c69e7399bbe
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CtfCpuUsageStateInput.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CtfCpuUsageStateInput.java
new file mode 100644
index 0000000..6b1b5a9
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/internal/lttng2/kernel/core/stateprovider/CtfCpuUsageStateInput.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Ericsson
+ * Copyright (c) 2012 École Polytechnique de Montréal
+ * Copyright (c) 2012 Matthew Khouzam <matthew.khouzam@ericsson.com>
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider;
+
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.LttngStrings;
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.StateValues;
+import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent;
+import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
+import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
+import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.tmf.core.statesystem.AbstractStateChangeInput;
+import org.eclipse.linuxtools.tmf.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.tmf.core.statevalue.TmfStateValue;
+
+/**
+ * @author Matthew Khouzam
+ * @since 2.0
+ */
+public class CtfCpuUsageStateInput extends AbstractStateChangeInput {
+
+ private int threadsNode = -1;
+ private int cpusNode = -1;
+
+ /**
+ * @param trace the trace to view
+ */
+ public CtfCpuUsageStateInput(CtfTmfTrace trace) {
+ super(trace, CtfTmfEvent.class, "LTTng Kernel CPU Usage"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void assignTargetStateSystem(org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder ssb) {
+ /* We can only set up the locations once the state system is assigned */
+ super.assignTargetStateSystem(ssb);
+ threadsNode = ss.getQuarkAbsoluteAndAdd(Attributes.THREADS);
+ cpusNode = ss.getQuarkAbsoluteAndAdd(Attributes.CPUS);
+ }
+
+ @Override
+ protected void eventHandle(ITmfEvent ev) {
+ int quark;
+ ITmfStateValue value;
+
+ /*
+ * AbstractStateChangeInput should have already checked for the correct
+ * class type
+ */
+ CtfTmfEvent event = (CtfTmfEvent) ev;
+ if (event.getEventName().equals(LttngStrings.SCHED_SWITCH)) {
+ final ITmfEventField content = event.getContent();
+
+ final Integer currentCPUNode = ss.getQuarkRelativeAndAdd(cpusNode, String.valueOf(event.getCPU()));
+
+ final long ts = event.getTimestamp().getValue();
+
+ Integer prevTid = ((Long) content.getField(LttngStrings.PREV_TID).getValue()).intValue();
+ String nextProcessName = (String) content.getField(LttngStrings.NEXT_COMM).getValue();
+ Integer nextTid = ((Long) content.getField(LttngStrings.NEXT_TID).getValue()).intValue();
+
+ Integer formerThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, prevTid.toString());
+ Integer newCurrentThreadNode = ss.getQuarkRelativeAndAdd(threadsNode, nextTid.toString());
+
+
+ try {
+
+ final ITmfStateValue userMode = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_RUN_USERMODE);
+ final ITmfStateValue waitMode = TmfStateValue.newValueInt(StateValues.PROCESS_STATUS_WAIT);
+
+ /* Set the status of the process that got scheduled out. */
+ quark = ss.getQuarkRelativeAndAdd(formerThreadNode, Attributes.STATUS);
+ ss.modifyAttribute(ts, waitMode, quark);
+
+ /* Set the status of the new scheduled process */
+ quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.STATUS);
+ ss.modifyAttribute(ts, userMode, quark);
+
+ /* Set the exec name of the new process */
+ quark = ss.getQuarkRelativeAndAdd(newCurrentThreadNode, Attributes.EXEC_NAME);
+ value = TmfStateValue.newValueString(nextProcessName);
+ ss.modifyAttribute(ts, value, quark);
+
+
+ /* Set the current scheduled process on the relevant CPU */
+ quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.CURRENT_THREAD);
+ value = TmfStateValue.newValueInt(nextTid);
+ ss.modifyAttribute(ts, value, quark);
+
+ /* Set the status of the CPU itself */
+ if (nextTid > 0) {
+ value = userMode;
+ } else {
+ value = TmfStateValue.newValueInt(StateValues.CPU_STATUS_IDLE);
+ }
+ quark = ss.getQuarkRelativeAndAdd(currentCPUNode, Attributes.STATUS);
+ ss.modifyAttribute(ts, value, quark);
+ } catch (TimeRangeException e) {
+ e.printStackTrace();
+ } catch (AttributeNotFoundException e) {
+ e.printStackTrace();
+ } catch (StateValueTypeException e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
+}
diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/lttng2/kernel/core/trace/CtfKernelTrace.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/lttng2/kernel/core/trace/CtfKernelTrace.java
index 3ce5be1..0b28d70 100644
--- a/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/lttng2/kernel/core/trace/CtfKernelTrace.java
+++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.core/src/org/eclipse/linuxtools/lttng2/kernel/core/trace/CtfKernelTrace.java
@@ -19,6 +19,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.linuxtools.ctf.core.trace.CTFReaderException;
import org.eclipse.linuxtools.ctf.core.trace.CTFTrace;
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CtfCpuUsageStateInput;
import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CtfKernelStateInput;
import org.eclipse.linuxtools.tmf.core.TmfCommonConstants;
import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTrace;
@@ -36,18 +37,32 @@
*/
public class CtfKernelTrace extends CtfTmfTrace {
+
+ private ITmfStateSystem cpuUsageSS;
+
/**
* The file name of the History Tree
*/
public final static String HISTORY_TREE_FILE_NAME = "stateHistory.ht"; //$NON-NLS-1$
/**
+ * The file name of the CPU Tree
+ */
+ public final static String CPU_TREE_FILE_NAME= "cpuHistory.ht"; //$NON-NLS-1$
+
+ /**
* ID of the state system we will build
* @since 2.0
* */
public static final String STATE_ID = "org.eclipse.linuxtools.lttng2.kernel"; //$NON-NLS-1$
/**
+ * ID of the CPU Usage state system we will build
+ * @since 2.0
+ */
+ public static final String CPU_ID = "org.eclipse.linuxtools.lttng2.cpu"; //$NON-NLS-1$
+
+ /**
* Default constructor
*/
public CtfKernelTrace() {
@@ -95,6 +110,11 @@
ITmfStateSystem ss = StateSystemManager.loadStateHistory(htFile, htInput, STATE_ID, false);
fStateSystems.put(STATE_ID, ss);
- }
+ final File cpuFile = new File(supplDirectory + File.separator + CPU_TREE_FILE_NAME);
+ final IStateChangeInput cpuInput = new CtfCpuUsageStateInput(this);
+
+ ss = StateSystemManager.loadStateHistory(cpuFile, cpuInput, CPU_ID, false);
+ fStateSystems.put(CPU_ID, ss);
+ }
}
diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/META-INF/MANIFEST.MF b/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/META-INF/MANIFEST.MF
index 0df94c5..273c7c6 100644
--- a/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/META-INF/MANIFEST.MF
+++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/META-INF/MANIFEST.MF
@@ -16,4 +16,5 @@
org.eclipse.linuxtools.tmf.ui;bundle-version="2.0.0",
org.eclipse.linuxtools.lttng2.core;bundle-version="2.0.0",
org.eclipse.linuxtools.lttng2.ui;bundle-version="2.0.0",
- org.eclipse.linuxtools.lttng2.kernel.core;bundle-version="2.0.0"
+ org.eclipse.linuxtools.lttng2.kernel.core;bundle-version="2.0.0",
+ org.swtchart;bundle-version="0.7.0"
diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/plugin.xml b/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/plugin.xml
index 6404556..73bee09 100644
--- a/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/plugin.xml
+++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/plugin.xml
@@ -30,6 +30,15 @@
name="%resources.view.name"
restorable="true">
</view>
+ <view
+ allowMultiple="false"
+ category="org.eclipse.linuxtools.lttng2.ui.views.category"
+ class="org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.cpu.CPUUsage"
+ icon="icons/obj16/garland16.png"
+ id="org.eclipse.linuxtools.lttng2.kernel.ui.views.cpu"
+ name="CPU Usage"
+ restorable="false">
+ </view>
</extension>
<extension
point="org.eclipse.linuxtools.tmf.ui.tracetype">
diff --git a/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/cpu/CPUUsage.java b/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/cpu/CPUUsage.java
new file mode 100644
index 0000000..076e140
--- /dev/null
+++ b/lttng/org.eclipse.linuxtools.lttng2.kernel.ui/src/org/eclipse/linuxtools/internal/lttng2/kernel/ui/views/cpu/CPUUsage.java
@@ -0,0 +1,601 @@
+package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.cpu;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
+import org.eclipse.linuxtools.internal.lttng2.kernel.core.StateValues;
+import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;
+import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.tmf.core.exceptions.StateSystemDisposedException;
+import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
+import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
+import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
+import org.swtchart.Chart;
+import org.swtchart.IAxis;
+import org.swtchart.IBarSeries;
+import org.swtchart.ISeries;
+import org.swtchart.ISeries.SeriesType;
+import org.swtchart.ISeriesSet;
+import org.swtchart.LineStyle;
+import org.swtchart.Range;
+
+/**
+ * @author Matthew Khouzam
+ * @since 2.0
+ */
+public class CPUUsage extends TmfView {
+ /**
+ * The id
+ */
+ public static final String ID = "org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.cpu"; //$NON-NLS-1$
+
+ private ISeriesSet fSeriesSet;
+ private Chart fChart;
+ private CtfKernelTrace fTrace;
+ private ITmfStateSystem fKSS;
+
+ /**
+ *
+ */
+ public CPUUsage() {
+ super(ID);
+ resetXY();
+ }
+
+ private void resetXY() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ String seriesId = "CPU Usage"; //$NON-NLS-1$
+ fChart = new Chart(parent, SWT.NONE);
+ fChart.getTitle().setText(seriesId);
+ fChart.getAxisSet().getXAxis(0).getTitle().setText("Time"); //$NON-NLS-1$
+ fChart.getAxisSet().getYAxis(0).getTitle().setText("%"); //$NON-NLS-1$
+ fChart.getAxisSet().getXAxis(0).getGrid().setStyle(LineStyle.NONE);
+ fChart.getAxisSet().getYAxis(0).getGrid().setStyle(LineStyle.NONE);
+ fSeriesSet = fChart.getSeriesSet();
+ IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
+ if (editor instanceof ITmfTraceEditor) {
+ ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
+ if (trace instanceof CtfKernelTrace) {
+ fTrace = (CtfKernelTrace) trace;
+ } else {
+ return;
+ }
+ }
+ if (fTrace != null) {
+ fKSS = fTrace.getStateSystem(CtfKernelTrace.CPU_ID);
+ fKSS.waitUntilBuilt();
+ if (fKSS != null) {
+ updateView(new TmfTimeRange(fTrace.getStartTime(), new CtfTmfTimestamp(fTrace.getStartTime().getValue() + 100000000)));
+ }
+ }
+
+ }
+
+ @Override
+ public void setFocus() {
+ }
+
+ Random rnd = new Random();
+
+ /**
+ * @return
+ */
+ private static Display getDisplay() {
+ Display display = Display.getCurrent();
+ // may be null if outside the UI thread
+ if (display == null) {
+ display = Display.getDefault();
+ }
+ return display;
+ }
+
+ /**
+ * @param signal
+ * the selected experiment
+ */
+ @TmfSignalHandler
+ public void traceSelected(final TmfTraceSelectedSignal signal) {
+ if (signal.getTrace() instanceof CtfKernelTrace) {
+ if (signal.getTrace().equals(fTrace)) {
+ return;
+ }
+ fTrace = (CtfKernelTrace) signal.getTrace();
+ fKSS = fTrace.getStateSystem(CtfKernelTrace.CPU_ID);
+ fKSS.waitUntilBuilt();
+ }
+ else {
+ return;
+ }
+ updateView(new TmfTimeRange(fTrace.getStartTime(), new CtfTmfTimestamp(fTrace.getStartTime().getValue() + 100000000)));
+ }
+
+ /**
+ * @param signal
+ * the time range of the experiment
+ */
+ @TmfSignalHandler
+ public void timeRangeUpdated(TmfRangeSynchSignal signal) {
+ TmfTimeRange value = signal.getCurrentRange();
+ if (fKSS == null) {
+ return;
+ }
+ updateView(value);
+ }
+
+ /**
+ * @param signal
+ */
+ private void updateView(TmfTimeRange signal) {
+ final long start = Math.max(fKSS.getStartTime(), signal.getStartTime().getValue());
+ ITmfTimestamp timeEnd = signal.getEndTime();
+ int tempNumCPU = 1;
+ try {
+ tempNumCPU = fKSS.getSubAttributes(fKSS.getQuarkAbsolute(Attributes.CPUS), false).size();
+ } catch (AttributeNotFoundException e) {
+ }
+ final int numCPU = tempNumCPU;
+ final int numRequests = 60;
+
+ final long stateStartTime = Math.max(start, fKSS.getStartTime());
+ long stateEndTime = Math.min(fKSS.getCurrentEndTime(), Math.max(timeEnd.getValue(), start));
+ if (start != stateStartTime) {
+ stateEndTime = stateStartTime + 100000000L;
+ }
+ final long end = stateEndTime;
+ final long delta = end - start;
+
+ final List<Integer> pidQuarks = getPids();
+
+ final List<Process> names = getValidThreadNames(pidQuarks, start, end);
+ pidQuarks.clear();
+
+ for (Process elem : names) {
+ pidQuarks.add(elem.getPidQuark());
+ }
+
+ double xd[] = new double[numRequests];
+ long x[] = new long[numRequests];
+ final String xAxisLabel[] = new String[numRequests];
+ long roundedDelta = getLargeInterval(delta);
+ if (roundedDelta > numRequests) {
+ setupXAxis(start, numRequests, stateStartTime, end, delta, xd, x, xAxisLabel, roundedDelta);
+
+ /*
+ * Put the top 9 threads here and the "rest"
+ */
+
+ final int listSize = Math.min(names.size(), 10);
+ if (listSize >= 2) {
+ List<Process> subList = names.subList(0, listSize - 1);
+
+ Process[] croppedNames = subList.toArray(new Process[listSize - 1]);
+ final String threadNames[] = new String[croppedNames.length + 1];
+ for (int i = 0; i < croppedNames.length; i++) {
+ threadNames[i] = croppedNames[i].toString();
+ }
+ threadNames[croppedNames.length] = "other"; //$NON-NLS-1$
+ final int numSeries = threadNames.length;
+
+ /*
+ * Get CPU usage
+ */
+ final double[][] y = fillYBar(numCPU, pidQuarks, start, end, numRequests, numSeries);
+
+ if (getDisplay() != null && names.size() > 0) {
+ getDisplay().asyncExec(new Runnable() {
+
+ @Override
+ public void run() {
+
+ final IAxis xAxis = fChart.getAxisSet().getXAxis(0);
+ xAxis.enableCategory(true);
+ xAxis.setCategorySeries(xAxisLabel);
+ for (int i = 0; i < numSeries; i++) {
+
+ String data = threadNames[i];
+ IBarSeries bs = (IBarSeries) fSeriesSet.getSeries(data);
+ if (bs == null) {
+ bs = initSeries(data);
+
+ }
+ bs.setYSeries(y[i]);
+ }
+ /* culling here */
+ for (ISeries series : fSeriesSet.getSeries()) {
+ String id = series.getId();
+ boolean found = false;
+ for (String tName : threadNames) {
+ if (tName.equals(id)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ fSeriesSet.deleteSeries(id);
+ }
+ }
+
+ for (String seriesID : threadNames) {
+
+ fSeriesSet.bringToFront(seriesID);
+ fSeriesSet.getSeries(seriesID).enableStack(true);
+ }
+
+ fChart.getAxisSet().getYAxes()[0].setRange(new Range(0, 100));
+ fChart.getAxisSet().adjustRange();
+ fChart.redraw();
+ }
+
+ /**
+ * @param data
+ * @return
+ */
+ private IBarSeries initSeries(String data) {
+ final int color = data.hashCode();
+ final int r = (color >> 16) & 0xff;
+ final int g = (color >> 8) & 0xff;
+ final int b = color & 0xff;
+ IBarSeries bs = (IBarSeries) fSeriesSet.createSeries(SeriesType.BAR, data);
+ bs.enableStack(true);
+ bs.setBarColor(new Color(Display.getDefault(), r, g, b));
+ bs.setBarPadding(0);
+ return bs;
+ }
+
+ });
+ }
+ }
+ }
+ }
+
+ private static void setupXAxis(final long start, final int numRequests, final long stateStartTime, final long end, final long delta, double[] xd, long[] x, final String[] xAxisLabel, long roundedDelta) {
+ int numIntervals = 8;
+ ArrayList<Long> positions = new ArrayList<Long>();
+ long clippedStart = getFirstVal(start, roundedDelta, numIntervals);
+ long roundedStep = roundedDelta / numIntervals;
+ long stepValue = clippedStart;
+ while ((roundedStep + stepValue) < start) {
+ stepValue += roundedStep;
+ }
+ while (end > stepValue) {
+ positions.add(stepValue);
+ stepValue += roundedStep;
+ }
+ int curPos = 0;
+ for (int req = 0; req < numRequests; req++) {
+ xAxisLabel[req] = new String(""); //$NON-NLS-1$
+ long trs = (long) (stateStartTime + (delta) * ((double) req / numRequests));
+ long tre = (long) (stateStartTime + (delta) * ((double) (req + 1) / numRequests));
+ x[req] = (trs / 2 + tre / 2);
+ if (curPos < positions.size()) {
+ long curVal = positions.get(curPos);
+ while ((curVal < trs) && (curPos < positions.size())) {
+ curVal = positions.get(curPos);
+ curPos++;
+ }
+ if ((curVal > trs) && (curVal < tre)) {
+ xAxisLabel[req] = new CtfTmfTimestamp(curVal).toString();
+ }
+
+ }
+ xd[req] = x[req];
+ }
+ }
+
+ private static long getLargeInterval(final long delta) {
+ final double values[] = { 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5 };
+ long diffSize = delta;
+ long precision = 1;
+ while (diffSize >= 1) {
+ diffSize /= 10;
+ precision *= 10;
+ }
+ precision /= 10;
+ for (int i = 0; i < values.length; i++) {
+ final long retVal = (long) (values[i] * precision);
+ if (retVal > delta) {
+ return retVal;
+ }
+ }
+ return precision;
+ }
+
+ private static long getFirstVal(final long startVal, final long roundedDelta, int numIntervals) {
+ long retVal = (startVal / roundedDelta) * roundedDelta;
+ long step = roundedDelta / numIntervals;
+ while ((retVal + step) < startVal) {
+ retVal += step;
+ }
+ return retVal;
+ }
+
+ /**
+ * @param pidQuarks
+ * @param start
+ * @param end
+ * @return
+ */
+ private List<Process> getValidThreadNames(final List<Integer> pidQuarks, final long start, final long end) {
+ final List<Process> names = globalCPUUsage(pidQuarks, start, end);
+
+ // new ArrayList<Process> = (pidQuarks, stateStartTime, stateEndTime);
+ ArrayList<Process> elemsToRemove = new ArrayList<Process>();
+ for (Process elem : names) {
+ if ((elem.getExecTime() == 0.0) || (elem.getPid() == 0)) {
+ elemsToRemove.add(elem);
+ }
+ }
+ for (Process elem : elemsToRemove) {
+ names.remove(elem);
+ }
+ Collections.sort(names);
+ return names;
+ }
+
+ private List<Process> globalCPUUsage(final List<Integer> pidQuarks, final long start, final long end) {
+ List<Process> names = new ArrayList<CPUUsage.Process>();
+ for (int pidQuark : pidQuarks) {
+ try {
+ String pid = fKSS.getAttributeName(pidQuark);
+ int execNameQuark = fKSS.getQuarkRelative(pidQuark, Attributes.EXEC_NAME);
+ String execName = fKSS.querySingleState(start, execNameQuark).getStateValue().unboxStr();
+ final String NULL_STRING = "nullValue"; //$NON-NLS-1$
+ if (execName.equals(NULL_STRING)) {
+ execName = fKSS.querySingleState(end, execNameQuark).getStateValue().unboxStr();
+ }
+ if (execName.equals(NULL_STRING)) {
+ execName = "UNKNOWN"; //$NON-NLS-1$
+ }
+ int statusQuark = fKSS.getQuarkRelative(pidQuark, Attributes.STATUS);
+ List<ITmfStateInterval> intervals = fKSS.queryHistoryRange(statusQuark, start, end);
+ if (intervals.size() > 10) {
+ PrintWriter tw;
+
+ try {
+ tw = new PrintWriter(new BufferedWriter(new FileWriter("/tmp/intervals-" + pid + ".csv", true))); //$NON-NLS-1$//$NON-NLS-2$
+ tw.println("starth, startl, endh, endl, attribute, value, mod"); //$NON-NLS-1$
+ for (ITmfStateInterval interval : intervals) {
+ final long bil = 1000000000L;
+ tw.println(interval.getStartTime() / bil + "," + interval.getStartTime() % bil + ", " + interval.getEndTime() / bil + ", " + interval.getEndTime() % bil + ", " + interval.getAttribute() + ", " + interval.getStateValue()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ }
+ tw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ double factor = 1.0;
+ double data[] = cpuUsageToDouble(start, end, intervals, factor);
+ names.add(new Process(execName, Integer.parseInt(pid), data, pidQuark));
+ } catch (AttributeNotFoundException e) {
+ } catch (TimeRangeException e) {
+ } catch (StateSystemDisposedException e) {
+ } catch (StateValueTypeException e) {
+ }
+ }
+ return names;
+ }
+
+ private double[][] fillYBar(final int numberOfCPUS, final List<Integer> pidQuarkList, long startTime, long endTime, final int numRequests, final int numSeries) {
+ double y[][] = new double[numSeries][numRequests];
+ final int otherRow = numSeries - 1;
+ Arrays.fill(y[otherRow], 0.0);
+
+ double fullY[][] = new double[pidQuarkList.size()][numRequests];
+ List<Process> processes = new ArrayList<Process>();
+
+ final double step = (endTime - startTime) / numRequests;
+ final double factor = 100.0 / step / numberOfCPUS;
+ int pids[] = new int[pidQuarkList.size()];
+
+ for (int i = 0; i < pidQuarkList.size(); i++) {
+ Arrays.fill(fullY[i], 0.0);
+ int pidQuark = pidQuarkList.get(i);
+ int statusQuark;
+
+ try {
+ final String attributeName = fKSS.getAttributeName(pidQuark);
+ if (!attributeName.equals("Unknown")) { //$NON-NLS-1$
+ int execNameQuark = fKSS.getQuarkRelative(pidQuark, Attributes.EXEC_NAME);
+ String execName = fKSS.querySingleState(startTime, execNameQuark).getStateValue().unboxStr();
+ if (execName.equals("nullValue")) { //$NON-NLS-1$
+ execName = fKSS.querySingleState(endTime, execNameQuark).getStateValue().unboxStr();
+ }
+ pids[i] = Integer.parseInt(attributeName);
+ statusQuark = fKSS.getQuarkRelative(pidQuark, Attributes.STATUS);
+ List<ITmfStateInterval> execTimes = fKSS.queryHistoryRange(statusQuark, startTime, endTime);
+ for (ITmfStateInterval interval : execTimes) {
+ final int stateStatus = interval.getStateValue().unboxInt();
+ if (stateStatus == StateValues.PROCESS_STATUS_RUN_USERMODE ||
+ stateStatus == (StateValues.PROCESS_STATUS_RUN_SYSCALL))
+ {
+ long currTime = startTime;
+ final long iet = interval.getEndTime();
+ final long ist = interval.getStartTime();
+
+ for (int req = 0; req < numRequests && (currTime < iet); req++) {
+ long newStart = Math.max(currTime, ist);
+ long newEnd = Math.min(currTime + (long) step, iet);
+ currTime = startTime + (long) (step * (req + 1.0));
+ newStart = Math.min(newEnd, newStart);
+ final long delta = newEnd - newStart;
+ fullY[i][req] += delta * factor;
+ }
+ }
+ }
+ Process p = new Process(execName, pids[i], fullY[i], pidQuark);
+ processes.add(p);
+ }
+
+ } catch (AttributeNotFoundException e) {
+ } catch (TimeRangeException e) {
+ } catch (StateSystemDisposedException e) {
+ } catch (StateValueTypeException e) {
+ }
+ }
+ List<Process> processesToRemove = new ArrayList<CPUUsage.Process>();
+ for (Process p : processes) {
+ if (p.getPid() == 0) {
+ processesToRemove.add(p);
+ }
+ }
+ for (Process p : processesToRemove) {
+ processes.remove(p);
+ }
+ processesToRemove.clear();
+ Collections.sort(processes);
+
+ for (int i = 0; i < numSeries; i++) {
+ final boolean addToList = i < otherRow;
+ final Process process = processes.get(i);
+ boolean addToOther = !(process.pid == 0 || addToList);
+ for (int req = 0; req < numRequests; req++) {
+ final double valueToAdd = process.getExecTimeArray()[req];
+ if (valueToAdd > 70) {
+ new Object();
+ }
+ if (addToList) {
+ y[i][req] = valueToAdd;
+ }
+ else if (addToOther) {
+ y[otherRow][req] += valueToAdd;
+ }
+ }
+ }
+ return y;
+ }
+
+ private static double[] cpuUsageToDouble(final long startTime, final long endTime, List<ITmfStateInterval> intervals, double factor) throws StateValueTypeException {
+ int i = 0;
+ double data[] = new double[intervals.size()];
+ for (ITmfStateInterval interval : intervals) {
+ int stateStatus = interval.getStateValue().unboxInt();
+
+ if (stateStatus == StateValues.PROCESS_STATUS_RUN_USERMODE ||
+ stateStatus == (StateValues.PROCESS_STATUS_RUN_SYSCALL))
+ {
+ long newStart = Math.max(startTime, interval.getStartTime());
+ long newEnd = Math.min(endTime, interval.getEndTime());
+ newStart = Math.min(newEnd, newStart);
+ final long delta = newEnd - newStart;
+ data[i] += delta * factor;
+ }
+ i++;
+
+ }
+ return data;
+ }
+
+ /**
+ * @return
+ */
+ private List<Integer> getPids() {
+ List<Integer> children = new ArrayList<Integer>();
+ try {
+ int threadQuark = fKSS.getQuarkAbsolute(Attributes.THREADS);
+ children = fKSS.getSubAttributes(threadQuark, false);
+ } catch (AttributeNotFoundException e) {
+ e.printStackTrace();
+ }
+ return children;
+ }
+
+ class Process implements Comparable<Process> {
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return procName + ":" + pid; //$NON-NLS-1$
+ }
+
+ /**
+ * @return the procName
+ */
+ public String getProcName() {
+ return procName;
+ }
+
+ /**
+ * @return the pid
+ */
+ public int getPid() {
+ return pid;
+ }
+
+ public double[] getExecTimeArray() {
+ return execTimeArray;
+ }
+
+ /**
+ * @return the execTime
+ */
+ public double getExecTime() {
+ return execTime;
+ }
+
+ /**
+ * @return the pidQuark
+ */
+ public int getPidQuark() {
+ return pidQuark;
+ }
+
+ public Process(String name, int pid_, double executionTime[], int pidQuark_) {
+ procName = name;
+ pid = pid_;
+ execTimeArray = executionTime;
+ pidQuark = pidQuark_;
+ double acc = 0;
+ for (double execTime_ : executionTime) {
+ acc += execTime_;
+ }
+ execTime = acc;
+ }
+
+ final int pidQuark;
+ final String procName;
+ final int pid;
+ final double execTime;
+ final double execTimeArray[];
+
+ @Override
+ public int compareTo(Process o) {
+ if (execTime < o.execTime) {
+ return 1;
+ }
+ if (execTime > o.execTime) {
+ return -1;
+ }
+ return 0;
+ }
+
+ }
+}