| /******************************************************************************* |
| * Copyright (c) 2018 É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 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.lttng2.ust.core.tests.perf.cygprofile; |
| |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.File; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.Objects; |
| |
| 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.profiling.core.callgraph.ICallGraphProvider; |
| import org.eclipse.tracecompass.analysis.profiling.core.callstack.CallStackAnalysis; |
| import org.eclipse.tracecompass.ctf.core.tests.shared.CtfBenchmarkTrace; |
| import org.eclipse.tracecompass.internal.analysis.profiling.core.callgraph.CallGraphAnalysis; |
| import org.eclipse.tracecompass.internal.lttng2.ust.core.callstack.LttngUstCallStackAnalysis; |
| import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace; |
| 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.event.ITmfEvent; |
| 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.TmfTrace; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; |
| import org.eclipse.tracecompass.tmf.ctf.core.tests.shared.CtfTmfTestTraceUtils; |
| import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| /** |
| * Benchmarks the lttng ust callstack analysis execution and call graph |
| * execution |
| * |
| * @author Geneviève Bastien |
| */ |
| @SuppressWarnings("restriction") |
| @RunWith(Parameterized.class) |
| public class CallStackAndGraphBenchmark { |
| |
| /** |
| * Test ID for this benchmark |
| */ |
| public static final String TEST_ID = "org.eclipse.tracecompass.lttng2.ust#CallStack#"; |
| private static final String TEST_CALLSTACK_BUILD = "Building Callstack (%s)"; |
| private static final String TEST_CALLSTACK_PARSESEGSTORE = "Callstack segment store (%s)"; |
| private static final String TEST_CALLGRAPH_BUILD = "Building CallGraph (%s)"; |
| |
| private static final int LOOP_COUNT = 25; |
| |
| private final String fName; |
| private final String fTestTrace; |
| private final int fLoopCount; |
| |
| private static String getPathFromCtfTestTrace(@NonNull CtfTestTrace testTrace) { |
| CtfTmfTrace ctftrace = CtfTmfTestTraceUtils.getTrace(testTrace); |
| String path = Objects.requireNonNull(ctftrace.getPath()); |
| ctftrace.dispose(); |
| return path; |
| } |
| |
| /** |
| * Get the traces on which to run the benchmark |
| * |
| * @return The arrays of parameters |
| */ |
| @Parameters(name = "{index}: {0}") |
| public static Iterable<Object[]> getParameters() { |
| return Arrays.asList(new Object[][] { |
| { CtfTestTrace.CYG_PROFILE.name(), getPathFromCtfTestTrace(CtfTestTrace.CYG_PROFILE), LOOP_COUNT }, |
| { CtfBenchmarkTrace.UST_QMLSCENE.name(), CtfBenchmarkTrace.UST_QMLSCENE.getTracePath().toString(), LOOP_COUNT }, |
| { CtfBenchmarkTrace.UST_VLC.name(), CtfBenchmarkTrace.UST_VLC.getTracePath().toString(), 5}, |
| }); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @param name |
| * The name of this test |
| * @param tracePath |
| * The path to the trace to the trace to test |
| * @param loopCount |
| * The number of times to run the benchmark |
| */ |
| public CallStackAndGraphBenchmark(String name, String tracePath, int loopCount) { |
| fName = name; |
| fTestTrace = tracePath; |
| fLoopCount = loopCount; |
| } |
| |
| /** |
| * Run benchmark for the trace |
| * |
| * @throws TmfTraceException |
| * Exceptions thrown getting the trace |
| */ |
| @Test |
| public void runCpuBenchmark() throws TmfTraceException { |
| Performance perf = Performance.getDefault(); |
| PerformanceMeter callStackBuildPm = Objects.requireNonNull(perf.createPerformanceMeter(TEST_ID + String.format(TEST_CALLSTACK_BUILD, fName))); |
| perf.tagAsSummary(callStackBuildPm, String.format(TEST_CALLSTACK_BUILD, fName), Dimension.CPU_TIME); |
| PerformanceMeter callStackSegStorePm = Objects.requireNonNull(perf.createPerformanceMeter(TEST_ID + String.format(TEST_CALLSTACK_PARSESEGSTORE, fName))); |
| perf.tagAsSummary(callStackSegStorePm, String.format(TEST_CALLSTACK_PARSESEGSTORE, fName), Dimension.CPU_TIME); |
| PerformanceMeter callgraphBuildPm = Objects.requireNonNull(perf.createPerformanceMeter(TEST_ID + String.format(TEST_CALLGRAPH_BUILD, fName))); |
| perf.tagAsSummary(callgraphBuildPm, String.format(TEST_CALLGRAPH_BUILD, fName), Dimension.CPU_TIME); |
| |
| for (int i = 0; i < fLoopCount; i++) { |
| TmfTrace trace = null; |
| try { |
| trace = getTrace(); |
| trace.traceOpened(new TmfTraceOpenedSignal(this, trace, null)); |
| CallStackAnalysis callStackModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, CallStackAnalysis.class, LttngUstCallStackAnalysis.ID); |
| assertNotNull(callStackModule); |
| callStackModule.triggerAutomatically(false); |
| |
| // Benchmark the call stack analysis |
| callStackBuildPm.start(); |
| TmfTestHelper.executeAnalysis(callStackModule); |
| callStackBuildPm.stop(); |
| |
| // Benchmark the segment store iteration |
| ISegmentStore<@NonNull ISegment> segmentStore = callStackModule.getSegmentStore(); |
| assertNotNull(segmentStore); |
| callStackSegStorePm.start(); |
| // Iterate through the whole segment store |
| Iterator<ISegment> iterator = segmentStore.iterator(); |
| while (iterator.hasNext()) { |
| iterator.next(); |
| } |
| callStackSegStorePm.stop(); |
| |
| ICallGraphProvider callGraphModule = callStackModule.getCallGraph(); |
| assertTrue(callGraphModule instanceof CallGraphAnalysis); |
| // Benchmark the call graph analysis |
| callgraphBuildPm.start(); |
| TmfTestHelper.executeAnalysis((CallGraphAnalysis) callGraphModule); |
| callgraphBuildPm.stop(); |
| |
| /* |
| * Delete the supplementary files, so that the next iteration rebuilds the state |
| * system. |
| */ |
| File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace)); |
| for (File file : suppDir.listFiles()) { |
| file.delete(); |
| } |
| |
| } finally { |
| if (trace != null) { |
| trace.dispose(); |
| } |
| } |
| } |
| callStackBuildPm.commit(); |
| callgraphBuildPm.commit(); |
| } |
| |
| private TmfTrace getTrace() throws TmfTraceException { |
| LttngUstTrace trace = new LttngUstTrace(); |
| trace.initTrace(null, fTestTrace, ITmfEvent.class); |
| return trace; |
| } |
| |
| } |