1 /*******************************************************************************
2 * Copyright (c) 2016 Ericsson
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 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.lttng2
.kernel
.core
.tests
.perf
.analysis
.tid
;
12 import static org
.junit
.Assert
.fail
;
15 import java
.util
.List
;
16 import java
.util
.Random
;
18 import org
.eclipse
.jdt
.annotation
.NonNull
;
19 import org
.eclipse
.jdt
.annotation
.Nullable
;
20 import org
.eclipse
.test
.performance
.Dimension
;
21 import org
.eclipse
.test
.performance
.Performance
;
22 import org
.eclipse
.test
.performance
.PerformanceMeter
;
23 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.tid
.TidAnalysisModule
;
24 import org
.eclipse
.tracecompass
.lttng2
.kernel
.core
.tests
.perf
.analysis
.kernel
.KernelAnalysisBenchmark
;
25 import org
.eclipse
.tracecompass
.lttng2
.kernel
.core
.trace
.LttngKernelTrace
;
26 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
27 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
28 import org
.eclipse
.tracecompass
.testtraces
.ctf
.CtfTestTrace
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfAnalysisException
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.tests
.shared
.TmfTestHelper
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
33 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
34 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.event
.CtfTmfEvent
;
35 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.tests
.shared
.CtfTmfTestTraceUtils
;
36 import org
.junit
.Test
;
39 * Benchmarks some typical usages of the thread id analysis
41 * @author Matthew Khouzam
43 public class TidAnalysisUsageBenchmark
{
45 private static final String TEST_GET_RUNNING_THREAD
= "TID: Threads On CPU";
46 private static final int LOOP_COUNT
= 25;
47 private static final long SEED
= 65423897234L;
48 private static final int NUM_CPU_QUERIES
= 20000;
51 * Run the benchmark with "trace2"
54 public void testTrace2() {
55 runTest(CtfTestTrace
.TRACE2
, "Trace2");
59 * Run the benchmark with "many threads"
62 public void testManyThreads() {
63 runTest(CtfTestTrace
.MANY_THREADS
, "ManyThreads");
67 * Run the benchmark with "django httpd"
70 public void testDjangoHttpd() {
71 runTest(CtfTestTrace
.DJANGO_HTTPD
, "Django httpd");
74 private static TidAnalysisModule
getModule(@NonNull CtfTestTrace testTrace
, @NonNull LttngKernelTrace trace
) {
75 TidAnalysisModule module
= null;
76 String path
= CtfTmfTestTraceUtils
.getTrace(testTrace
).getPath();
79 /* Initialize the analysis module */
80 module
= new TidAnalysisModule();
82 trace
.initTrace(null, path
, CtfTmfEvent
.class);
83 module
.setTrace(trace
);
84 TmfTestHelper
.executeAnalysis(module
);
85 } catch (TmfAnalysisException
| TmfTraceException e
) {
91 private static void deleteSupplementaryFiles(ITmfTrace trace
) {
93 * Delete the supplementary files at the end of the benchmarks
95 File suppDir
= new File(TmfTraceManager
.getSupplementaryFileDir(trace
));
96 for (File file
: suppDir
.listFiles()) {
101 private static void runTest(@NonNull CtfTestTrace testTrace
, String testName
) {
103 /* First, complete the analysis */
104 LttngKernelTrace trace
= new LttngKernelTrace();
105 deleteSupplementaryFiles(trace
);
106 TidAnalysisModule module
= getModule(testTrace
, trace
);
108 /* Benchmark some query use cases */
109 benchmarkGetThreadOnCpu(testName
, module
);
111 deleteSupplementaryFiles(trace
);
115 CtfTmfTestTraceUtils
.dispose(testTrace
);
119 * Benchmarks getting a thread running on a random CPU from the kernel
120 * analysis at fixed intervals. This use case mimics an analysis that reads
121 * events and needs to get the currently running thread for those events.
123 private static void benchmarkGetThreadOnCpu(String testName
, TidAnalysisModule module
) {
125 Performance perf
= Performance
.getDefault();
126 PerformanceMeter pmRunningThread
= perf
.createPerformanceMeter(KernelAnalysisBenchmark
.TEST_ID
+ testName
+ ": " + TEST_GET_RUNNING_THREAD
);
127 perf
.tagAsSummary(pmRunningThread
, TEST_GET_RUNNING_THREAD
+ '(' + testName
+ ')', Dimension
.CPU_TIME
);
130 ITmfStateSystem ss
= module
.getStateSystem();
132 fail("The state system is null");
136 /* Get the number of CPUs */
140 List
<@NonNull Integer
> cpus
= ss
.getSubAttributes(ITmfStateSystem
.ROOT_ATTRIBUTE
, false);
141 cpuCount
= cpus
.size();
142 } catch (AttributeNotFoundException e
) {
143 fail(e
.getMessage());
146 fail("Impossible to get the number of CPUs");
149 /* Get the step and start time of the queries */
150 long startTime
= ss
.getStartTime();
151 long endTime
= ss
.getCurrentEndTime();
152 long step
= Math
.floorDiv(endTime
- startTime
, NUM_CPU_QUERIES
);
155 fail("Trace is too short to run the get thread on CPU benchmark");
158 /* Verify the query work by fetching a value at the end of the trace */
159 Integer threadOnCpu
= module
.getThreadOnCpuAtTime(0, endTime
);
160 if (threadOnCpu
== null) {
161 fail("null thread on CPU at the end of the trace. Something is not right with the state system");
164 for (int i
= 0; i
< LOOP_COUNT
; i
++) {
165 /* Get the thread running on a random CPU at fixed intervals */
166 Random randomGenerator
= new Random(SEED
);
167 pmRunningThread
.start();
168 for (long nextTime
= startTime
; nextTime
< endTime
; nextTime
+= step
) {
169 int cpu
= Math
.abs(randomGenerator
.nextInt()) % cpuCount
;
170 module
.getThreadOnCpuAtTime(cpu
, nextTime
);
172 pmRunningThread
.stop();
174 pmRunningThread
.commit();