1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.app.tracing.benchmark
17 
18 import android.os.Trace
19 import android.perftests.utils.BenchmarkState
20 import android.perftests.utils.PerfStatusReporter
21 import android.platform.test.annotations.EnableFlags
22 import android.platform.test.flag.junit.SetFlagsRule
23 import android.platform.test.rule.EnsureDeviceSettingsRule
24 import androidx.test.ext.junit.runners.AndroidJUnit4
25 import androidx.test.filters.SmallTest
26 import com.android.app.tracing.coroutines.createCoroutineTracingContext
27 import com.android.app.tracing.coroutines.nameCoroutine
28 import com.android.app.tracing.coroutines.traceCoroutine
29 import com.android.systemui.Flags
30 import kotlinx.coroutines.delay
31 import kotlinx.coroutines.launch
32 import kotlinx.coroutines.runBlocking
33 import kotlinx.coroutines.withContext
34 import kotlinx.coroutines.yield
35 import org.junit.After
36 import org.junit.Assert
37 import org.junit.Before
38 import org.junit.ClassRule
39 import org.junit.Rule
40 import org.junit.Test
41 import org.junit.runner.RunWith
42 
43 private val TAG: String = TraceContextMicroBenchmark::class.java.simpleName
44 
45 @RunWith(AndroidJUnit4::class)
46 @EnableFlags(Flags.FLAG_COROUTINE_TRACING)
47 class TraceContextMicroBenchmark {
48 
49     @get:Rule val perfStatusReporter = PerfStatusReporter()
50 
51     @get:Rule val setFlagsRule = SetFlagsRule()
52 
53     companion object {
54         @JvmField @ClassRule(order = 1) var ensureDeviceSettingsRule = EnsureDeviceSettingsRule()
55     }
56 
57     @Before
beforenull58     fun before() {
59         Assert.assertTrue(Trace.isEnabled())
60     }
61 
62     @After
afternull63     fun after() {
64         Assert.assertTrue(Trace.isEnabled())
65     }
66 
ensureSuspendnull67     private suspend fun ensureSuspend(state: BenchmarkState) {
68         state.pauseTiming()
69         delay(1)
70         state.resumeTiming()
71     }
72 
73     @SmallTest
74     @Test
testSingleTraceSectionnull75     fun testSingleTraceSection() {
76         val state = perfStatusReporter.benchmarkState
77         runBlocking(createCoroutineTracingContext("root")) {
78             while (state.keepRunning()) {
79                 traceCoroutine("hello-world") { ensureSuspend(state) }
80             }
81         }
82     }
83 
84     @SmallTest
85     @Test
testNestedContextnull86     fun testNestedContext() {
87         val state = perfStatusReporter.benchmarkState
88 
89         val context1 = createCoroutineTracingContext("scope1")
90         val context2 = nameCoroutine("scope2")
91         runBlocking {
92             while (state.keepRunning()) {
93                 withContext(context1) {
94                     traceCoroutine("hello") {
95                         traceCoroutine("world") {
96                             withContext(context2) {
97                                 traceCoroutine("hallo") {
98                                     traceCoroutine("welt") { ensureSuspend(state) }
99                                     ensureSuspend(state)
100                                 }
101                             }
102                             ensureSuspend(state)
103                         }
104                         ensureSuspend(state)
105                     }
106                 }
107             }
108         }
109     }
110 
111     @SmallTest
112     @Test
testInterleavedLaunchnull113     fun testInterleavedLaunch() {
114         val state = perfStatusReporter.benchmarkState
115 
116         runBlocking(createCoroutineTracingContext("root")) {
117             val job1 =
118                 launch(nameCoroutine("scope1")) {
119                     while (true) {
120                         traceCoroutine("hello") {
121                             traceCoroutine("world") { yield() }
122                             yield()
123                         }
124                     }
125                 }
126             val job2 =
127                 launch(nameCoroutine("scope2")) {
128                     while (true) {
129                         traceCoroutine("hallo") {
130                             traceCoroutine("welt") { yield() }
131                             yield()
132                         }
133                     }
134                 }
135             while (state.keepRunning()) {
136                 repeat(10_000) { traceCoroutine("main-loop") { yield() } }
137             }
138             job1.cancel()
139             job2.cancel()
140         }
141     }
142 }
143