--- /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.lttng2.kernel.core.tests.perf.analysis.syscall;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.test.performance.Dimension;
+import org.eclipse.test.performance.Performance;
+import org.eclipse.test.performance.PerformanceMeter;
+import org.eclipse.tracecompass.analysis.os.linux.core.tid.TidAnalysisModule;
+import org.eclipse.tracecompass.internal.analysis.os.linux.core.latency.SystemCallLatencyAnalysis;
+import org.eclipse.tracecompass.lttng2.kernel.core.tests.perf.analysis.kernel.KernelAnalysisBenchmark;
+import org.eclipse.tracecompass.lttng2.kernel.core.trace.LttngKernelTrace;
+import org.eclipse.tracecompass.segmentstore.core.ISegment;
+import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
+import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+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.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent;
+import org.eclipse.tracecompass.tmf.ctf.core.tests.shared.CtfTmfTestTraceUtils;
+import org.junit.Test;
+
+/**
+ * Benchmarks the system call latency analysis
+ *
+ * @author Geneviève Bastien
+ */
+public class SystemCallAnalysisUsageBenchmark {
+
+ /**
+ * Test test ID for the system call analysis benchmarks
+ */
+ public static final String TEST_ID = "org.eclipse.tracecompass#System Call Analysis#";
+ private static final String TEST_ITERATE_CPU = "Iterate cpu (%s)";
+ private static final String TEST_ITERATE_MEMORY = "Iterate memory (%s)";
+ private static final String TEST_INTERSECTION_CPU = "Intersection cpu (%s)";
+ private static final String TEST_INTERSECTION_MEMORY = "Intersection memory (%s)";
+
+ private static final int LOOP_COUNT = 25;
+
+ private static void deleteSupplementaryFiles(ITmfTrace trace) {
+ /*
+ * Delete the supplementary files at the beginning and end of the benchmarks
+ */
+ File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace));
+ for (File file : suppDir.listFiles()) {
+ file.delete();
+ }
+ }
+
+ private static SystemCallLatencyAnalysis getModule(@NonNull CtfTestTrace testTrace, @NonNull LttngKernelTrace trace) {
+ SystemCallLatencyAnalysis module = null;
+ String path = CtfTmfTestTraceUtils.getTrace(testTrace).getPath();
+
+ try {
+
+ // Make sure the TID analysis has run on this trace
+ trace.initTrace(null, path, CtfTmfEvent.class);
+ deleteSupplementaryFiles(trace);
+
+ trace.traceOpened(new TmfTraceOpenedSignal(trace, trace, null));
+ IAnalysisModule tidModule = trace.getAnalysisModule(TidAnalysisModule.ID);
+ assertNotNull(tidModule);
+ tidModule.schedule();
+ tidModule.waitForCompletion();
+
+ /* Initialize the analysis module */
+ module = new SystemCallLatencyAnalysis();
+ module.setId("test");
+ module.setTrace(trace);
+ TmfTestHelper.executeAnalysis(module);
+ } catch (TmfAnalysisException | TmfTraceException e) {
+ fail(e.getMessage());
+ }
+ return module;
+ }
+
+ /**
+ * Run the benchmark with "trace2"
+ */
+ @Test
+ public void testTrace2() {
+ runTest(CtfTestTrace.TRACE2, "Trace2");
+ }
+
+ /**
+ * Run the benchmark with "many thread"
+ */
+ @Test
+ public void testManyThreads() {
+ runTest(CtfTestTrace.MANY_THREADS, "Many threads");
+ }
+
+ /**
+ * Run the benchmark with "django httpd"
+ */
+ @Test
+ public void testDjangoHttpd() {
+ runTest(CtfTestTrace.DJANGO_HTTPD, "Django HTTPD");
+ }
+
+ private static void runTest(@NonNull CtfTestTrace testTrace, String traceName) {
+ /* First, complete the analysis */
+ LttngKernelTrace trace = new LttngKernelTrace();
+ SystemCallLatencyAnalysis module = getModule(testTrace, trace);
+
+ long segmentEnd = benchmarkIteration(traceName, module);
+ benchmarkIntersection(traceName, module, trace.getStartTime().getValue(), segmentEnd);
+
+ /*
+ * Delete the supplementary files at the end of the benchmarks
+ */
+ deleteSupplementaryFiles(trace);
+
+ module.dispose();
+ trace.dispose();
+
+ CtfTmfTestTraceUtils.dispose(testTrace);
+ }
+
+ /**
+ * Benchmarks iterating through all the segments of the analysis
+ */
+ private static long benchmarkIteration(String testName, SystemCallLatencyAnalysis module) {
+
+ Performance perf = Performance.getDefault();
+ PerformanceMeter pmCpu = perf.createPerformanceMeter(KernelAnalysisBenchmark.TEST_ID + String.format(TEST_ITERATE_CPU, testName));
+ perf.tagAsSummary(pmCpu, "Syscall " + String.format(TEST_ITERATE_CPU, testName), Dimension.CPU_TIME);
+
+ PerformanceMeter pmMemory = perf.createPerformanceMeter(KernelAnalysisBenchmark.TEST_ID + String.format(TEST_ITERATE_MEMORY, testName));
+ perf.tagAsSummary(pmMemory, "Syscall " + String.format(TEST_ITERATE_MEMORY, testName), Dimension.USED_JAVA_HEAP);
+
+ ISegmentStore<@NonNull ISegment> ss = module.getSegmentStore();
+ if (ss == null) {
+ fail("The segment store is null");
+ return -1;
+ }
+
+ long endTime = -1;
+
+ /** Benchmark for CPU time */
+ for (int i = 0; i < LOOP_COUNT; i++) {
+ /* Make a full query at fixed intervals */
+ pmCpu.start();
+ for (ISegment segment : ss) {
+ endTime = Math.max(endTime, segment.getEnd());
+ }
+ pmCpu.stop();
+ }
+
+ /** Benchmark for memory usage */
+ for (int i = 0; i < LOOP_COUNT; i++) {
+ /* Make a full query at fixed intervals */
+ System.gc();
+ pmMemory.start();
+ for (ISegment segment : ss) {
+ endTime = Math.max(endTime, segment.getEnd());
+ }
+ System.gc();
+ pmMemory.stop();
+ }
+
+ pmCpu.commit();
+ pmMemory.commit();
+ return endTime;
+ }
+
+ /**
+ * Benchmarks iterating through all the segments of the analysis
+ */
+ private static void benchmarkIntersection(String testName, SystemCallLatencyAnalysis module, long start, long end) {
+
+ Performance perf = Performance.getDefault();
+ PerformanceMeter pmCpu = perf.createPerformanceMeter(KernelAnalysisBenchmark.TEST_ID + String.format(TEST_INTERSECTION_CPU, testName));
+ perf.tagAsSummary(pmCpu, "Syscall " + String.format(TEST_INTERSECTION_CPU, testName), Dimension.CPU_TIME);
+
+ PerformanceMeter pmMemory = perf.createPerformanceMeter(KernelAnalysisBenchmark.TEST_ID + String.format(TEST_INTERSECTION_MEMORY, testName));
+ perf.tagAsSummary(pmMemory, "Syscall " + String.format(TEST_INTERSECTION_MEMORY, testName), Dimension.USED_JAVA_HEAP);
+
+ ISegmentStore<@NonNull ISegment> ss = module.getSegmentStore();
+ if (ss == null) {
+ fail("The segment store is null");
+ return;
+ }
+
+ /** Benchmark for CPU time */
+ for (int i = 0; i < LOOP_COUNT; i++) {
+ /* Make a full query at fixed intervals */
+ long intersectStart = start;
+ long intersectEnd = end;
+ pmCpu.start();
+ for (int j = 0; j < 10; j++) {
+ ss.getIntersectingElements(intersectStart, intersectEnd);
+ long step = (long) ((intersectEnd - intersectStart) * 0.1);
+ intersectStart += step;
+ intersectEnd -= step;
+ }
+ pmCpu.stop();
+ }
+
+ /** Benchmark for memory usage */
+ for (int i = 0; i < LOOP_COUNT; i++) {
+ /* Make a full query at fixed intervals */
+ List<Iterable<ISegment>> lists = new ArrayList<>();
+ long intersectStart = start;
+ long intersectEnd = end;
+ System.gc();
+ pmMemory.start();
+ for (int j = 0; j < 5; j++) {
+ Iterable<@NonNull ISegment> elements = ss.getIntersectingElements(intersectStart, intersectEnd);
+ lists.add(elements);
+ long step = (long) ((intersectEnd - intersectStart) * 0.2);
+ intersectStart += step;
+ intersectEnd -= step;
+ }
+ System.gc();
+ pmMemory.stop();
+ }
+
+ pmCpu.commit();
+ pmMemory.commit();
+ }
+
+}