This view keeps track of page allocation/deallocation events in the kernel.
It consists of a plot and a menu for thread selection. For a given time range,
the menu only lists threads in which there was activity. Values in the plot
are relative to the beginning of the selected trace.
Change-Id: Ie5605b7211828fd01accb920a5a735500fcae4b2
Signed-off-by: Najib Arbaoui <arbaouinajib@gmail.com>
Signed-off-by: Samuel Gagnon <samuel.gagnon92@gmail.com>
Reviewed-on: https://git.eclipse.org/r/65957
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Tested-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
class="org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.trace.TmfXmlKernelTraceStub">
</tracetype>
</module>
+ <module
+ analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule"
+ automatic="false"
+ id="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryanalysismodule"
+ name="Kernel Memory Usage Test Analysis">
+ <tracetype
+ applies="true"
+ class="org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub">
+ </tracetype>
+ </module>
</extension>
<extension
point="org.eclipse.linuxtools.tmf.core.tracetype">
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tracecompass.analysis.os.linux.core.tests.kernelmemoryusage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryStateProvider;
+import org.eclipse.tracecompass.analysis.os.linux.core.tests.Activator;
+import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.trace.TmfXmlKernelTraceStub;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.event.TmfEvent;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestHelper;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test suite for the {@link KernelMemoryAnalysisModule} class
+ *
+ * @author Julien Daoust
+ * @author Najib Arbaoui
+ */
+public class KernelMemoryStateProviderTest {
+
+ private static final String KERNEL_MEMORY_USAGE_FILE = "testfiles/KernelMemoryAnalysis_testTrace.xml";
+ private static final long PAGE_SIZE = 4096;
+ private ITmfTrace fTrace;
+ private KernelMemoryAnalysisModule fModule = null;
+ private SortedMap<Long, Long> threadEvent = new TreeMap<>();
+
+ private static void deleteSuppFiles(ITmfTrace trace) {
+ /* Remove supplementary files */
+ File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace));
+ for (File file : suppDir.listFiles()) {
+ file.delete();
+ }
+ }
+
+ /**
+ * Setup the trace for the tests
+ */
+ @Before
+ public void setUp() {
+ ITmfTrace trace = new TmfXmlKernelTraceStub();
+ IPath filePath = Activator.getAbsoluteFilePath(KERNEL_MEMORY_USAGE_FILE);
+ IStatus status = trace.validate(null, filePath.toOSString());
+ if (!status.isOK()) {
+ fail(status.getException().getMessage());
+ }
+ try {
+ trace.initTrace(null, filePath.toOSString(), TmfEvent.class);
+ } catch (TmfTraceException e) {
+ fail(e.getMessage());
+ }
+ deleteSuppFiles(trace);
+ ((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null));
+ fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelMemoryAnalysisModule.class, KernelMemoryAnalysisModule.ID);
+ assertNotNull(fModule);
+ fTrace = trace;
+ }
+
+ /**
+ * Clean up
+ */
+ @After
+ public void tearDown() {
+ deleteSuppFiles(fTrace);
+ fTrace.dispose();
+ }
+
+ /**
+ * Test that the analysis executes without problems
+ */
+ @Test
+ public void testAnalysisExecution() {
+ /* Make sure the analysis hasn't run yet */
+ assertNull(fModule.getStateSystem());
+
+ /* Execute the analysis */
+ assertTrue(TmfTestHelper.executeAnalysis(fModule));
+ assertNotNull(fModule.getStateSystem());
+ }
+
+ /**
+ * Test allocation and deallocation of kernel Memory
+ */
+ @Test
+ public void testAllocationDeallocationMemory() {
+ fModule.schedule();
+ fModule.waitForCompletion();
+ ITmfStateSystem ss = fModule.getStateSystem();
+ assertNotNull(ss);
+ assertEquals(1L, ss.getStartTime());
+ assertEquals(30L, ss.getCurrentEndTime());
+ long totalMemory = 0;
+ threadEvent.put(1L, PAGE_SIZE); // kmem_mm_page_alloc at timestamp = 1
+ threadEvent.put(2L, -PAGE_SIZE); // kmem_mm_page_free at timestamp = 2
+ threadEvent.put(3L, -PAGE_SIZE); // kmem_mm_page_free at timestamp = 3
+ threadEvent.put(17L, PAGE_SIZE); // kmem_mm_page_alloc at timestamp = 17
+ threadEvent.put(22L, -PAGE_SIZE); // kmem_mm_page_free at timestamp = 22
+ threadEvent.put(28L, -PAGE_SIZE); // kmem_mm_page_free at timestamp = 28
+ threadEvent.put(29L, PAGE_SIZE); // kmem_mm_page_alloc at timestamp = 29
+ threadEvent.put(30L, PAGE_SIZE); // kmem_mm_page_alloc at timestamp = 30
+
+ // loop a Map and check if all allocation and deallocation of kernel
+ // memory are done proprely
+ for (Map.Entry<Long, Long> entry : threadEvent.entrySet()) {
+ try {
+ int tidQuark = ss.getQuarkAbsolute(KernelMemoryStateProvider.OTHER_TID);
+ ITmfStateInterval kernelState = ss.querySingleState(entry.getKey(), tidQuark);
+ long value = kernelState.getStateValue().unboxLong();
+ totalMemory += entry.getValue();
+ assertEquals(totalMemory, value);
+
+ } catch (StateSystemDisposedException | AttributeNotFoundException e) {
+ fail(e.getMessage());
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<!-- **************************************************************************************
+* Simple Kernel Memory trace, with simple events kmem_mm_page_alloc et kmem_mm_page_free
+**************************************************************************************** -->
+<trace>
+<set_aspects>
+<field name="cpu" value="1" type="int" />
+</set_aspects>
+<event timestamp="1" name="kmem_mm_page_alloc">
+<field name="cpu" value="0" type="int" />
+<field name="tid" value="proc1" type="string" />
+</event>
+<event timestamp="2" name="kmem_mm_page_free">
+<field name="cpu" value="1" type="int" />
+<field name="tid" value="proc2" type="string" />
+</event>
+<event timestamp="3" name="kmem_mm_page_free">
+<field name="cpu" value="1" type="int" />
+<field name="tid" value="proc1" type="string" />
+</event>
+<event timestamp="17" name="kmem_mm_page_alloc">
+<field name="cpu" value="0" type="int" />
+<field name="tid" value="proc3" type="string" />
+</event>
+<event timestamp="22" name="kmem_mm_page_free">
+<field name="cpu" value="1" type="int" />
+<field name="tid" value="proc4" type="string" />
+</event>
+<event timestamp="28" name="kmem_mm_page_free">
+<field name="cpu" value="1" type="int" />
+<field name="tid" value="proc2" type="string" />
+</event>
+<event timestamp="29" name="kmem_mm_page_alloc">
+<field name="cpu" value="0" type="int" />
+<field name="tid" value="proc4" type="string" />
+</event>
+<event timestamp="30" name="kmem_mm_page_alloc">
+<field name="cpu" value="0" type="int" />
+<field name="tid" value="proc3" type="string" />
+</event>
+</trace>
\ No newline at end of file
org.eclipse.tracecompass.analysis.os.linux.core.cpuusage,
org.eclipse.tracecompass.analysis.os.linux.core.event.aspect,
org.eclipse.tracecompass.analysis.os.linux.core.kernel,
+ org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage,
org.eclipse.tracecompass.analysis.os.linux.core.latency,
org.eclipse.tracecompass.analysis.os.linux.core.model,
org.eclipse.tracecompass.analysis.os.linux.core.signals,
Bundle-Name = Trace Compass Linux Kernel Analysis Core Plug-in
tracetype.type.kernel = Linux Kernel Trace
-analysis.linuxkernel = Linux Kernel
+analysis.linuxkernel = Linux Kernel
analysis.cpuusage = CPU usage
analysis.latency = System Call Latency
analysis.contextswitch = Context switch
+analysis.kernelmemory = Kernel memory usage
class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
</tracetype>
</module>
+ <module
+ analysis_module="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule"
+ id="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemory"
+ name="%analysis.kernelmemory">
+ <tracetype
+ applies="true"
+ class="org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace">
+ </tracetype>
+ </module>
</extension>
</plugin>
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tracecompass.analysis.os.linux.core.kernelmemoryusage;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
+import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+/**
+ * This analysis module creates a stateprovider that keeps track of the memory
+ * allocated and deallocated by the kernel
+ *
+ * @author Samuel Gagnon
+ * @since 2.0
+ */
+public class KernelMemoryAnalysisModule extends TmfStateSystemAnalysisModule {
+
+ /**
+ * Analysis ID, it should match that in the plugin.xml file
+ */
+ public static final @NonNull String ID = "org.eclipse.tracecompass.analysis.os.linux.core.kernelmemory"; //$NON-NLS-1$
+
+ /**
+ * Each thread attribute in the tree has an attribute for keeping the lowest memory
+ * value for that thread during the trace. (Those values can be negative because we
+ * don't have access to a memory dump before the trace)
+ */
+ public static final @NonNull String THREAD_LOWEST_MEMORY_VALUE = "lowestMemory"; //$NON-NLS-1$
+
+ @Override
+ protected @NonNull ITmfStateProvider createStateProvider() {
+ ITmfTrace trace = checkNotNull(getTrace());
+ IKernelAnalysisEventLayout layout;
+
+ if (trace instanceof IKernelTrace) {
+ layout = ((IKernelTrace) trace).getKernelEventLayout();
+ } else {
+ /* Fall-back to the base LttngEventLayout */
+ layout = IKernelAnalysisEventLayout.DEFAULT_LAYOUT;
+ }
+ return new KernelMemoryStateProvider(trace, layout);
+ }
+}
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2016 Polytechnique de Montréal
+ *
+ * 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.tracecompass.analysis.os.linux.core.kernelmemoryusage;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelTidAspect;
+import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
+import org.eclipse.tracecompass.statesystem.core.StateSystemBuilderUtils;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+
+/**
+ * Creates a state system and computes the total memory usage for all threads
+ * and for each selected thread from a kernel trace. It examines the page
+ * allocation and deallocation events in the kernel to do so.
+ *
+ * The state provider also contains code that can query the state system.
+ *
+ * @author Samuel Gagnon
+ * @since 2.0
+ */
+public class KernelMemoryStateProvider extends AbstractTmfStateProvider {
+
+ /**
+ * Special string to save memory allocation when tid is not known
+ */
+ public static final String OTHER_TID = "other"; //$NON-NLS-1$
+
+ /* Version of this state provider */
+ private static final int VERSION = 1;
+
+ private static final int PAGE_SIZE = 4096;
+
+ private IKernelAnalysisEventLayout fLayout;
+
+ /**
+ * Constructor
+ *
+ * @param trace
+ * trace
+ * @param layout
+ * layout
+ */
+ public KernelMemoryStateProvider(@NonNull ITmfTrace trace, IKernelAnalysisEventLayout layout) {
+ super(trace, "Kernel:Memory"); //$NON-NLS-1$
+ fLayout = layout;
+ }
+
+ @Override
+ public int getVersion() {
+ return VERSION;
+ }
+
+ @Override
+ public ITmfStateProvider getNewInstance() {
+ return new KernelMemoryStateProvider(getTrace(), fLayout);
+ }
+
+ @Override
+ protected void eventHandle(@NonNull ITmfEvent event) {
+ String name = event.getName();
+
+ long inc;
+ if (name.equals(fLayout.eventKmemPageAlloc())) {
+ inc = PAGE_SIZE;
+ } else if (name.equals(fLayout.eventKmemPageFree())) {
+ inc = -PAGE_SIZE;
+ } else {
+ return;
+ }
+
+ try {
+ ITmfStateSystemBuilder ss = checkNotNull(getStateSystemBuilder());
+ long ts = event.getTimestamp().getValue();
+
+ Integer tidField = KernelTidAspect.INSTANCE.resolve(event);
+ String tid;
+ if (tidField == null) {
+ // if the TID is not available
+ tid = OTHER_TID;
+ } else {
+ tid = tidField.toString();
+ }
+
+ int tidQuark = ss.getQuarkAbsoluteAndAdd(tid);
+ StateSystemBuilderUtils.incrementAttributeLong(ss, ts, tidQuark, inc);
+ long currentMemoryValue = ss.queryOngoingState(tidQuark).unboxLong();
+
+ /**
+ * We add an attribute to keep the lowest memory value for each
+ * thread. This quantity is used when we plot to avoid negative
+ * values.
+ */
+ int lowestMemoryQuark = ss.getQuarkRelativeAndAdd(tidQuark, KernelMemoryAnalysisModule.THREAD_LOWEST_MEMORY_VALUE);
+ ITmfStateValue lowestMemoryValue = ss.queryOngoingState(lowestMemoryQuark);
+ long previousLowest = lowestMemoryValue.isNull() ? 0 : lowestMemoryValue.unboxLong();
+
+ if (previousLowest > currentMemoryValue) {
+ ss.modifyAttribute(ts, TmfStateValue.newValueLong(currentMemoryValue), lowestMemoryQuark);
+ }
+ } catch (AttributeNotFoundException e) {
+ Activator.getDefault().logError(e.getMessage(), e);
+ }
+ }
+
+}
private static final String EXPIRES = "expires"; //$NON-NLS-1$
private static final String NOW = "now"; //$NON-NLS-1$
private static final String SOFT_EXPIRES = "softexpires"; //$NON-NLS-1$
+ private static final String KMEM_ALLOC = "kmem_mm_page_alloc"; //$NON-NLS-1$
+ private static final String KMEM_FREE = "kmem_mm_page_free"; //$NON-NLS-1$
/**
* Constructor, to be used by classes extending this one. To get an instance
public String eventCompatSyscallExitPrefix() {
return SYSCALL_EXIT_PREFIX;
}
+ /**
+ * @since 2.0
+ */
+ @Override
+ public String eventKmemPageAlloc() {
+ return KMEM_ALLOC;
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public String eventKmemPageFree() {
+ return KMEM_FREE;
+
+ }
// ------------------------------------------------------------------------
// Event field names
*/
String eventHRTimerExpireExit();
+ /**
+ * The kernel just allocated a page of memory.
+ * <p>
+ * In Linux, this typically means a user space application just got a page of
+ * ram.
+ *
+ * @return the event name
+ * @since 2.0
+ */
+ String eventKmemPageAlloc();
+
+ /**
+ * The kernel just deallocated a page of memory.
+ * <p>
+ * In Linux, this typically means a page of ram was just freed
+ *
+ * @return the event name
+ * @since 2.0
+ */
+ String eventKmemPageFree();
+
// ------------------------------------------------------------------------
// Event field names
// ------------------------------------------------------------------------
org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests",
org.eclipse.tracecompass.internal.analysis.os.linux.ui.actions;x-internal:=true,
org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests,org.eclipse.tracecompass.analysis.os.linux.ui.tests",
+ org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;x-internal:=true,
org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests",
org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests",
org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests"
latency.scatter.view.name = System Call Latency vs Time
latency.stats.view.name = System Call Latency Statistics
latency.density.view.name = System Call Density
+kernelmemoryusageview.view.name = Kernel Memory Usage View
name="%latency.density.view.name"
restorable="true">
</view>
+ <view
+ category="org.eclipse.linuxtools.lttng2.ui.views.category"
+ class="org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage.KernelMemoryUsageView"
+ icon="icons/eview16/memory-usage.png"
+ id="org.eclipse.tracecompass.analysis.os.linux.ui.kernelmemoryusageview"
+ name="%kernelmemoryusageview.view.name"
+ restorable="true">
+ </view>
</extension>
<extension
point="org.eclipse.linuxtools.tmf.core.analysis">
class="org.eclipse.tracecompass.analysis.os.linux.core.latency.SystemCallLatencyAnalysis">
</analysisModuleClass>
</output>
+ <output
+ class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput"
+ id="org.eclipse.tracecompass.analysis.os.linux.ui.kernelmemoryusageview">
+ <analysisModuleClass
+ class="org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule">
+ </analysisModuleClass>
+ </output>
</extension>
</plugin>
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;
+
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
+
+/**
+ * This class represents an entry in the tree viewer of the kernel memory usage
+ * View.
+ *
+ * @author mahdi zolnouri
+ */
+public class KernelMemoryUsageEntry extends TmfTreeViewerEntry {
+
+ private final String fTid;
+ private final String fProcessName;
+
+ /**
+ * Constructor
+ *
+ * @param tid
+ * The TID of the process
+ * @param name
+ * The thread's name
+ */
+ public KernelMemoryUsageEntry(String tid, String name) {
+ super(tid);
+ fTid = tid;
+ fProcessName = name;
+ }
+
+ /**
+ * Get the TID of the thread represented by this entry
+ *
+ * @return The thread's TID
+ */
+ public String getTid() {
+ return fTid;
+ }
+
+ /**
+ * Get the process name
+ *
+ * @return The process name
+ */
+ public String getProcessName() {
+ return fProcessName;
+ }
+}
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2016 Polytechnique de Montréal
+ *
+ * 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.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;
+
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelThreadInformationProvider;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryStateProvider;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
+
+/**
+ * Tree viewer to select which process to display in the kernel memory usage
+ * chart.
+ *
+ * @author Mahdi Zolnouri
+ * @author Wassim Nasrallah
+ * @author Najib Arbaoui
+ */
+public class KernelMemoryUsageTreeViewer extends AbstractTmfTreeViewer {
+
+ private KernelMemoryAnalysisModule fModule = null;
+ private String fSelectedThread = null;
+ private static final String[] COLUMN_NAMES = new String[] {
+ Messages.KernelMemoryUsageComposite_ColumnTID,
+ Messages.KernelMemoryUsageComposite_ColumnProcess
+ };
+
+ /* A map that saves the mapping of a thread ID to its executable name */
+ private final Map<String, String> fProcessNameMap = new HashMap<>();
+
+ /** Provides label for the Kernel memory usage tree viewer cells */
+ protected static class KernelMemoryLabelProvider extends TreeLabelProvider {
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ KernelMemoryUsageEntry obj = (KernelMemoryUsageEntry) element;
+ if (columnIndex == 0) {
+ return obj.getTid();
+ } else if (columnIndex == 1) {
+ return obj.getProcessName();
+ }
+ return element.toString();
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param parent
+ * The parent composite that holds this viewer
+ */
+ public KernelMemoryUsageTreeViewer(Composite parent) {
+ super(parent, false);
+ setLabelProvider(new KernelMemoryLabelProvider());
+ }
+
+ @Override
+ protected ITmfTreeColumnDataProvider getColumnDataProvider() {
+ return new ITmfTreeColumnDataProvider() {
+
+ @Override
+ public List<TmfTreeColumnData> getColumnData() {
+ /* All columns are sortable */
+ List<TmfTreeColumnData> columns = new ArrayList<>();
+ TmfTreeColumnData column = new TmfTreeColumnData(COLUMN_NAMES[0]);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ KernelMemoryUsageEntry n1 = (KernelMemoryUsageEntry) e1;
+ KernelMemoryUsageEntry n2 = (KernelMemoryUsageEntry) e2;
+
+ return n1.getTid().compareTo(n2.getTid());
+ }
+ });
+ columns.add(column);
+ column = new TmfTreeColumnData(COLUMN_NAMES[1]);
+ column.setComparator(new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ KernelMemoryUsageEntry n1 = (KernelMemoryUsageEntry) e1;
+ KernelMemoryUsageEntry n2 = (KernelMemoryUsageEntry) e2;
+
+ return n1.getProcessName().compareTo(n2.getProcessName());
+ }
+ });
+ columns.add(column);
+ return columns;
+ }
+ };
+ }
+
+ // ------------------------------------------------------------------------
+ // Operations
+ // ------------------------------------------------------------------------
+
+ @Override
+ protected void contentChanged(ITmfTreeViewerEntry rootEntry) {
+ String selectedThread = fSelectedThread;
+ if (selectedThread != null) {
+ /* Find the selected thread among the inputs */
+ for (ITmfTreeViewerEntry entry : rootEntry.getChildren()) {
+ if (entry instanceof KernelMemoryUsageEntry) {
+ if (selectedThread.equals(((KernelMemoryUsageEntry) entry).getTid())) {
+ List<ITmfTreeViewerEntry> list = Collections.singletonList(entry);
+ super.setSelection(list);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void initializeDataSource() {
+ /* Should not be called while trace is still null */
+ ITmfTrace trace = checkNotNull(getTrace());
+
+ fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelMemoryAnalysisModule.class, KernelMemoryAnalysisModule.ID);
+ if (fModule == null) {
+ return;
+ }
+ fModule.schedule();
+ fModule.waitForInitialization();
+ fProcessNameMap.clear();
+ }
+
+ @Override
+ protected ITmfTreeViewerEntry updateElements(long start, long end, boolean isSelection) {
+ if (isSelection || (start == end)) {
+ return null;
+ }
+ KernelMemoryAnalysisModule module = fModule;
+ if (getTrace() == null || module == null) {
+ return null;
+ }
+ module.waitForInitialization();
+ ITmfStateSystem ss = module.getStateSystem();
+ if (ss == null) {
+ return null;
+ }
+ ss.waitUntilBuilt();
+ TmfTreeViewerEntry root = new TmfTreeViewerEntry(""); //$NON-NLS-1$
+ List<ITmfTreeViewerEntry> entryList = root.getChildren();
+
+ try {
+ List<ITmfStateInterval> memoryStates = ss.queryFullState(start);
+ List<Integer> threadQuarkList = ss.getSubAttributes(ITmfStateSystem.ROOT_ATTRIBUTE, false);
+
+ for (Integer threadQuark : threadQuarkList) {
+ ITmfStateInterval threadMemoryInterval = memoryStates.get(threadQuark);
+ if (threadMemoryInterval.getEndTime() < end) {
+ String tid = ss.getAttributeName(threadQuark);
+ String procname = getProcessName(tid);
+ KernelMemoryUsageEntry obj = new KernelMemoryUsageEntry(tid, procname);
+ entryList.add(obj);
+ }
+ }
+ } catch (StateSystemDisposedException | AttributeNotFoundException e) {
+ Activator.getDefault().logError(e.getMessage(), e);
+ }
+ return root;
+ }
+
+ /*
+ * Get the process name from its TID by using the LTTng kernel analysis
+ * module
+ */
+ private String getProcessName(String tid) {
+ String execName = fProcessNameMap.get(tid);
+ if (execName != null) {
+ return execName;
+ }
+ if (tid.equals(KernelMemoryStateProvider.OTHER_TID)) {
+ fProcessNameMap.put(tid, tid);
+ return tid;
+ }
+ ITmfTrace trace = checkNotNull(getTrace());
+ KernelAnalysisModule kernelModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelAnalysisModule.class, KernelAnalysisModule.ID);
+ if (kernelModule == null) {
+ return tid;
+ }
+ execName = KernelThreadInformationProvider.getExecutableName(kernelModule, Integer.parseInt(tid));
+ if (execName == null) {
+ return tid;
+ }
+ fProcessNameMap.put(tid, execName);
+ return execName;
+ }
+
+ /**
+ * Set the currently selected thread ID
+ *
+ * @param tid
+ * The selected thread ID
+ */
+ public void setSelectedThread(String tid) {
+ fSelectedThread = tid;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
+import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfXYChartViewer;
+import org.eclipse.tracecompass.tmf.ui.views.TmfChartView;
+
+/**
+ * Memory usage view
+ *
+ * @author Samuel Gagnon
+ * @author Mahdi Zolnouri
+ * @author Wassim Nasrallah
+ */
+public class KernelMemoryUsageView extends TmfChartView {
+
+ /** ID string */
+ public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.ui.kernelmemoryusageview"; //$NON-NLS-1$
+
+ /*
+ * We need this reference to update the viewer when there is a new selection
+ */
+ private KernelMemoryUsageTreeViewer fTreeViewerReference = null;
+
+ /**
+ * Constructor
+ */
+ public KernelMemoryUsageView() {
+ super(Messages.MemoryUsageView_title);
+ }
+
+ @Override
+ protected TmfXYChartViewer createChartViewer(Composite parent) {
+ return new KernelMemoryUsageViewer(parent);
+ }
+
+ private final class SelectionChangeListener implements ISelectionChangedListener {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ Object structSelection = ((IStructuredSelection) selection).getFirstElement();
+ if (structSelection instanceof KernelMemoryUsageEntry) {
+ KernelMemoryUsageEntry entry = (KernelMemoryUsageEntry) structSelection;
+ fTreeViewerReference.setSelectedThread(entry.getTid());
+ ((KernelMemoryUsageViewer) getChartViewer()).setSelectedThread(entry.getTid());
+ }
+ }
+ }
+ }
+
+ @Override
+ protected @NonNull TmfViewer createLeftChildViewer(Composite parent) {
+ @NonNull
+ KernelMemoryUsageTreeViewer fTreeViewer = new KernelMemoryUsageTreeViewer(parent);
+ fTreeViewerReference = fTreeViewer;
+
+ fTreeViewer.addSelectionChangeListener(new SelectionChangeListener());
+
+ /* Initialize the viewers with the currently selected trace */
+ ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
+ if (trace != null) {
+ TmfTraceSelectedSignal signal = new TmfTraceSelectedSignal(this, trace);
+ fTreeViewer.traceSelected(signal);
+ fTreeViewerReference.traceSelected(signal);
+ }
+
+ fTreeViewer.getControl().addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ super.controlResized(e);
+ }
+ });
+ return fTreeViewer;
+ }
+}
--- /dev/null
+/**********************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;
+
+import java.text.DecimalFormat;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.tracecompass.analysis.os.linux.core.kernelmemoryusage.KernelMemoryAnalysisModule;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator;
+import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
+import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer;
+import org.swtchart.Chart;
+
+/**
+ * Memory usage view
+ *
+ * @author Samuel Gagnon
+ * @author Wassim Nasrallah
+ */
+public class KernelMemoryUsageViewer extends TmfCommonXLineChartViewer {
+
+ /**
+ * MemoryFormat
+ *
+ * @author Matthew Khouzam
+ */
+ private static final class MemoryFormat extends Format {
+ private static final long serialVersionUID = 3934127385682676804L;
+ private static final String KB = "KB"; //$NON-NLS-1$
+ private static final String MB = "MB"; //$NON-NLS-1$
+ private static final String GB = "GB"; //$NON-NLS-1$
+ private static final String TB = "TB"; //$NON-NLS-1$
+ private static final long KILO = 1024;
+ private static final Format FORMAT = new DecimalFormat("#.###"); //$NON-NLS-1$
+
+ @Override
+ public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+ if (obj instanceof Double) {
+ Double value = (Double) obj;
+ if (value == 0) {
+ return toAppendTo.append("0"); //$NON-NLS-1$
+ }
+ if (value > KILO * KILO * KILO * KILO) {
+ return toAppendTo.append(FORMAT.format(value / (KILO * KILO * KILO * KILO))).append(' ').append(TB);
+ }
+ if (value > KILO * KILO * KILO) {
+ return toAppendTo.append(FORMAT.format(value / (KILO * KILO * KILO))).append(' ').append(GB);
+ }
+ if (value > KILO * KILO) {
+ return toAppendTo.append(FORMAT.format(value / (KILO * KILO))).append(' ').append(MB);
+ }
+ return toAppendTo.append(FORMAT.format(value / (KILO))).append(' ').append(KB);
+ }
+ return toAppendTo;
+ }
+
+ @Override
+ public Object parseObject(String source, ParsePosition pos) {
+ return null;
+ }
+ }
+
+ private static final String NOT_SELECTED = "-1"; //$NON-NLS-1$
+
+ private TmfStateSystemAnalysisModule fModule = null;
+ private String fSelectedThread = NOT_SELECTED;
+
+ /**
+ * Constructor
+ *
+ * @param parent
+ * parent view
+ */
+ public KernelMemoryUsageViewer(Composite parent) {
+ super(parent, Messages.MemoryUsageViewer_title, Messages.MemoryUsageViewer_xAxis, Messages.MemoryUsageViewer_yAxis);
+ Chart chart = getSwtChart();
+ chart.getAxisSet().getYAxis(0).getTick().setFormat(new MemoryFormat());
+ chart.getLegend().setPosition(SWT.BOTTOM);
+ }
+
+ @Override
+ protected void initializeDataSource() {
+ ITmfTrace trace = getTrace();
+ if (trace != null) {
+ fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, TmfStateSystemAnalysisModule.class, KernelMemoryAnalysisModule.ID);
+ if (fModule == null) {
+ return;
+ }
+ fModule.schedule();
+ }
+ }
+
+ @Override
+ protected void updateData(long start, long end, int nb, IProgressMonitor monitor) {
+ TmfStateSystemAnalysisModule module = fModule;
+ if (getTrace() == null || module == null) {
+ return;
+ }
+
+ if (!module.waitForInitialization()) {
+ return;
+ }
+
+ ITmfStateSystem ss = module.getStateSystem();
+ if (ss == null) {
+ throw new IllegalStateException();
+ }
+
+ double[] xvalues = getXAxis(start, end, nb);
+ if (xvalues.length == 0) {
+ return;
+ }
+ setXAxis(xvalues);
+
+ try {
+ /**
+ * For a given time range, we plot two lines representing the memory
+ * allocation. The first line represent the total memory allocation
+ * of every process. The second line represent the memory allocation
+ * of the selected thread.
+ */
+ double[] totalKernelMemoryValues = new double[xvalues.length];
+ double[] selectedThreadValues = new double[xvalues.length];
+ for (int i = 0; i < xvalues.length; i++) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+
+ double x = xvalues[i];
+ long t = (long) x + getTimeOffset();
+
+ List<ITmfStateInterval> kernelState = ss.queryFullState(t);
+
+ /* The subattributes of the root are the different threads */
+ List<Integer> threadQuarkList = ss.getSubAttributes(-1, false);
+ /* We add the value of each thread to the total quantity */
+ for (Integer threadQuark : threadQuarkList) {
+ ITmfStateInterval threadMemoryInterval = kernelState.get(threadQuark);
+ long value = threadMemoryInterval.getStateValue().unboxLong();
+ totalKernelMemoryValues[i] += value;
+
+ String tid = ss.getAttributeName(threadQuark);
+ if (tid.equals(fSelectedThread)) {
+ selectedThreadValues[i] = value;
+ }
+ }
+ }
+
+ /**
+ * For each thread, we look for its lowest value since the beginning
+ * of the trace. This way, we can avoid negative values in the plot.
+ */
+ double totalKernelMemoryValuesShift = 0;
+ double selectThreadValuesShift = 0;
+
+ /*
+ * The lowest value we are searching is at the end of the current
+ * selected zone
+ */
+ List<ITmfStateInterval> kernelState = ss.queryFullState(end);
+ List<Integer> threadQuarkList = ss.getSubAttributes(-1, false);
+ /* We add the lowest value of each thread */
+ for (Integer threadQuark : threadQuarkList) {
+ int lowestMemoryQuark = ss.getQuarkRelative(threadQuark, KernelMemoryAnalysisModule.THREAD_LOWEST_MEMORY_VALUE);
+ ITmfStateInterval lowestMemoryInterval = kernelState.get(lowestMemoryQuark);
+ long lowestMemoryValue = lowestMemoryInterval.getStateValue().unboxLong();
+ // We want to add up a positive quantity.
+ totalKernelMemoryValuesShift -= lowestMemoryValue;
+
+ String tid = ss.getAttributeName(threadQuark);
+ if (tid.equals(fSelectedThread)) {
+ // We want to add up a positive quantity.
+ selectThreadValuesShift = -lowestMemoryValue;
+ }
+ }
+
+ /**
+ * We shift the two displayed lines up.
+ */
+ for (int i = 0; i < xvalues.length; i++) {
+ totalKernelMemoryValues[i] += totalKernelMemoryValuesShift;
+ selectedThreadValues[i] += selectThreadValuesShift;
+ }
+ setSeries(Messages.MemoryUsageViewer_Total, totalKernelMemoryValues);
+ if (fSelectedThread != NOT_SELECTED) {
+ setSeries(fSelectedThread, selectedThreadValues);
+ }
+ updateDisplay();
+
+ } catch (TimeRangeException | StateSystemDisposedException | AttributeNotFoundException e) {
+ Activator.getDefault().logError(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Set the selected thread ID, which will be graphed in this viewer
+ *
+ * @param tid
+ * The selected thread ID
+ */
+ public void setSelectedThread(String tid) {
+ cancelUpdate();
+ deleteSeries(fSelectedThread);
+ fSelectedThread = tid;
+ updateContent();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2016 École Polytechnique de Montréal
+ *
+ * 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.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage;
+
+import org.eclipse.osgi.util.NLS;
+
+@SuppressWarnings("javadoc")
+public class Messages {
+ private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.kernelmemoryusage.messages"; //$NON-NLS-1$
+
+ public static String KernelMemoryUsageComposite_ColumnProcess;
+ public static String KernelMemoryUsageComposite_ColumnTID;
+ public static String MemoryUsageView_title;
+ public static String MemoryUsageViewer_title;
+ public static String MemoryUsageViewer_xAxis;
+ public static String MemoryUsageViewer_yAxis;
+ public static String MemoryUsageViewer_Total;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
--- /dev/null
+###############################################################################
+# Copyright (c) 2016 École Polytechnique de Montréal
+#
+# 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
+###############################################################################
+
+MemoryUsageView_title=Memory Usage
+MemoryUsageViewer_title=Relative Kernel Memory Usage
+MemoryUsageViewer_xAxis=Time
+MemoryUsageViewer_yAxis=Memory Variation
+KernelMemoryUsageComposite_ColumnProcess=Process
+KernelMemoryUsageComposite_ColumnTID=TID
+MemoryUsageViewer_Total=Total
\ No newline at end of file
return "irq_softirq_exit"; //$NON-NLS-1$
}
+ @Override
+ public String eventKmemPageAlloc() {
+ return "kmem_mm_page_alloc"; //$NON-NLS-1$
+ }
+
+ @Override
+ public String eventKmemPageFree() {
+ return "kmem_mm_page_free"; //$NON-NLS-1$
+ }
+
public String x86IrqVectorsLocalTimerEntry() {
return X86_IRQ_VECTORS_LOCAL_TIMER_ENTRY;
}
private static final String HRTIMER_EXPIRES = "expires";
private static final String HRTIMER_NOW = "now";
private static final String HRTIMER_SOFT_EXPIRES = "softexpires";
+ private static final String KMEM_ALLOC = "mm_page_alloc";
+ private static final String KMEM_FREE = "mm_page_free";
/** All instances are the same. Only provide a static instance getter */
protected LttngEventLayout() {
return SYSCALL_EXIT_PREFIX;
}
+ /**
+ * @since 2.0
+ */
+ @Override
+ public String eventKmemPageAlloc() {
+ return KMEM_ALLOC;
+ }
+
+ /**
+ * @since 2.0
+ */
+ @Override
+ public String eventKmemPageFree() {
+ return KMEM_FREE;
+ }
+
// ------------------------------------------------------------------------
// Event field names
// ------------------------------------------------------------------------
return "timer:hrtimer_expire_exit"; //$NON-NLS-1$
}
+ @Override
+ public String eventKmemPageAlloc() {
+ return "kmem:page_alloc"; //$NON-NLS-1$
+ }
+
+ @Override
+ public String eventKmemPageFree() {
+ return "kmem:page_free"; //$NON-NLS-1$
+ }
+
// ------------------------------------------------------------------------
// Field names
// ------------------------------------------------------------------------
public String fieldHRtimerNow() {
return "now"; //$NON-NLS-1$
}
-
}