Loading tracinglib/benchmark/src/ThreadLocalMicroBenchmark.kt +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ import android.platform.test.flag.junit.SetFlagsRule import android.platform.test.rule.EnsureDeviceSettingsRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags import com.android.systemui.Flags.FLAG_COROUTINE_TRACING import java.util.concurrent.atomic.AtomicInteger import org.junit.After import org.junit.Assert Loading @@ -33,7 +33,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(Flags.FLAG_COROUTINE_TRACING) @EnableFlags(FLAG_COROUTINE_TRACING) class ThreadLocalMicroBenchmark { @get:Rule val setFlagsRule = SetFlagsRule() Loading tracinglib/benchmark/src/TraceContextMicroBenchmark.kt +2 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import androidx.test.filters.SmallTest import com.android.app.tracing.coroutines.createCoroutineTracingContext import com.android.app.tracing.coroutines.nameCoroutine import com.android.app.tracing.coroutines.traceCoroutine import com.android.systemui.Flags import com.android.systemui.Flags.FLAG_COROUTINE_TRACING import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking Loading @@ -41,7 +41,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(Flags.FLAG_COROUTINE_TRACING) @EnableFlags(FLAG_COROUTINE_TRACING) class TraceContextMicroBenchmark { @get:Rule val setFlagsRule = SetFlagsRule() Loading tracinglib/core/src/coroutines/CoroutineTracing.kt +21 −9 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ package com.android.app.tracing.coroutines import com.android.app.tracing.traceSection import com.android.systemui.Flags import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract Loading Loading @@ -223,10 +222,14 @@ public inline fun <T, R> R.traceCoroutine(crossinline spanName: () -> String, bl // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the // coroutine resumes when tracing is active, we won't know its name. try { if (Flags.coroutineTracing()) traceThreadLocal.get()?.beginCoroutineTrace(spanName()) if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.beginCoroutineTrace(spanName()) } return block() } finally { if (Flags.coroutineTracing()) traceThreadLocal.get()?.endCoroutineTrace() if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.endCoroutineTrace() } } } Loading @@ -239,10 +242,14 @@ public inline fun <T> traceCoroutine(crossinline spanName: () -> String, block: // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the // coroutine resumes when tracing is active, we won't know its name. try { if (Flags.coroutineTracing()) traceThreadLocal.get()?.beginCoroutineTrace(spanName()) if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.beginCoroutineTrace(spanName()) } return block() } finally { if (Flags.coroutineTracing()) traceThreadLocal.get()?.endCoroutineTrace() if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.endCoroutineTrace() } } } Loading @@ -259,9 +266,10 @@ public inline fun <T> traceCoroutine(spanName: String, block: () -> T): T { } /** * Returns the passed context if [Flags.coroutineTracing] is false. Otherwise, returns a new context * by adding [CoroutineTraceName] to the given context. The [CoroutineTraceName] in the passed * context will take precedence over the new [CoroutineTraceName]. * Returns the passed context if [com.android.systemui.Flags.coroutineTracing] is false. Otherwise, * returns a new context by adding [CoroutineTraceName] to the given context. The * [CoroutineTraceName] in the passed context will take precedence over the new * [CoroutineTraceName]. */ @PublishedApi internal inline fun addName( Loading @@ -269,7 +277,11 @@ internal inline fun addName( context: CoroutineContext, ): CoroutineContext { contract { callsInPlace(spanName, InvocationKind.AT_MOST_ONCE) } return if (Flags.coroutineTracing()) CoroutineTraceName(spanName()) + context else context return if (com.android.systemui.Flags.coroutineTracing()) { CoroutineTraceName(spanName()) + context } else { context } } @PublishedApi Loading tracinglib/core/src/coroutines/TraceContextElement.kt +9 −9 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.os.PerfettoTrace import android.os.SystemProperties import android.os.Trace import android.util.Log import com.android.systemui.Flags import java.lang.StackWalker.StackFrame import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.atomic.AtomicInteger Loading Loading @@ -60,10 +59,6 @@ internal object DebugSysProps { @JvmField val alwaysEnableContinuationCounting = SystemProperties.getBoolean("debug.coroutine_tracing.count_continuations_override", false) @JvmField val UsePerfettoSdk = SystemProperties.getBoolean("debug.coroutine_tracing.use_perfetto_sdk", false) } /** Loading Loading @@ -125,7 +120,7 @@ public fun createCoroutineTracingContext( walkStackForDefaultNames: Boolean = false, shouldIgnoreClassName: ((String) -> Boolean)? = null, ): CoroutineContext { return if (Flags.coroutineTracing()) { return if (com.android.systemui.Flags.coroutineTracing()) { TraceContextElement( name = name, isRoot = true, Loading Loading @@ -166,7 +161,11 @@ public fun nameCoroutine(name: String): CoroutineContext = nameCoroutine { name @Deprecated("Use .launchInTraced, .launchTraced, .shareInTraced, etc.") public inline fun nameCoroutine(name: () -> String): CoroutineContext { contract { callsInPlace(name, InvocationKind.AT_MOST_ONCE) } return if (Flags.coroutineTracing()) CoroutineTraceName(name()) else EmptyCoroutineContext return if (com.android.systemui.Flags.coroutineTracing()) { CoroutineTraceName(name()) } else { EmptyCoroutineContext } } private object PerfettoTraceConfig { Loading @@ -174,7 +173,7 @@ private object PerfettoTraceConfig { @JvmField val COROUTINE_CATEGORY: PerfettoTrace.Category = PerfettoTrace.Category("cc") init { if (DebugSysProps.UsePerfettoSdk) { if (android.os.Flags.perfettoSdkTracingV2()) { COROUTINE_CATEGORY.register() } } Loading Loading @@ -275,7 +274,8 @@ internal class TraceContextElement( // Don't use Perfetto SDK when inherited trace prefixes are used since it is a feature only // intended for testing, and only the `android.os.Trace` APIs currently have test shadows: private val usePerfettoSdk = DebugSysProps.UsePerfettoSdk && inheritedTracePrefix == null private val usePerfettoSdk = android.os.Flags.perfettoSdkTracingV2() && inheritedTracePrefix == null private var continuationId = if (usePerfettoSdk) nextRandomInt() else 0 Loading tracinglib/core/src/coroutines/TraceData.kt +16 −32 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ package com.android.app.tracing.coroutines import android.os.Trace import com.android.app.tracing.beginSlice import com.android.app.tracing.endSlice import com.android.systemui.Flags import java.util.ArrayDeque import kotlin.contracts.ExperimentalContracts import kotlin.math.max Loading @@ -39,7 +38,7 @@ private typealias TraceSection = String @PublishedApi internal class TraceDataThreadLocal : ThreadLocal<TraceStorage?>() { override fun initialValue(): TraceStorage? { return if (Flags.coroutineTracing()) { return if (com.android.systemui.Flags.coroutineTracing()) { TraceStorage(null) } else { null Loading Loading @@ -69,20 +68,7 @@ internal class TraceStorage(internal var data: TraceData?) { * * `>1` indicates the current coroutine is resumed inside another coroutine, e.g. due to an * unconfined dispatcher or [UNDISPATCHED] launch. */ internal var contIndex = -1 internal lateinit var continuationIds: IntArray private lateinit var debugCounterTrack: String init { if (DebugSysProps.UsePerfettoSdk) { continuationIds = IntArray(INITIAL_THREAD_LOCAL_STACK_SIZE) } if (DEBUG) { debugCounterTrack = "TCE#${Thread.currentThread().threadId()}" } } private var contIndex = -1 /** * Count of slices opened on the current thread due to current [TraceData] that must be closed Loading @@ -94,7 +80,14 @@ internal class TraceStorage(internal var data: TraceData?) { * it indicates there is already something very wrong with the trace, so we will not waste CPU * cycles error checking. */ internal var openSliceCount = ByteArray(INITIAL_THREAD_LOCAL_STACK_SIZE) private var openSliceCount = ByteArray(INITIAL_THREAD_LOCAL_STACK_SIZE) private var continuationIds: IntArray? = if (android.os.Flags.perfettoSdkTracingV2()) IntArray(INITIAL_THREAD_LOCAL_STACK_SIZE) else null private val debugCounterTrack: String? = if (DEBUG) "TCE#${Thread.currentThread().threadId()}" else null /** * Adds a new trace section to the current trace data. The slice will be traced on the current Loading Loading @@ -129,32 +122,24 @@ internal class TraceStorage(internal var data: TraceData?) { fun updateDataForContinuation(contextTraceData: TraceData?, contId: Int) { data = contextTraceData val n = ++contIndex if (DEBUG) { Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack, n) } if (DEBUG) Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack!!, n) if (n < 0 || MAX_THREAD_LOCAL_STACK_SIZE <= n) return // fail-safe var size = openSliceCount.size if (n >= size) { size = max(2 * size, MAX_THREAD_LOCAL_STACK_SIZE) openSliceCount = openSliceCount.copyInto(ByteArray(size)) if (::continuationIds.isInitialized) { continuationIds = continuationIds.copyInto(IntArray(size)) } continuationIds = continuationIds?.copyInto(IntArray(size)) } openSliceCount[n] = data?.beginAllOnThread() ?: 0 if (::continuationIds.isInitialized && 0 < contId) { continuationIds[n] = contId } if (0 < contId) continuationIds?.set(n, contId) } /** Update [data] for suspension */ fun restoreDataForSuspension(oldState: TraceData?): Int { data = oldState val n = contIndex-- if (DEBUG) { Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack, n) } if (n < 0 || MAX_THREAD_LOCAL_STACK_SIZE <= n) return 0 // fail-safe if (DEBUG) Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack!!, n) if (n < 0 || openSliceCount.size <= n) return 0 // fail-safe if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) { val lastState = openSliceCount[n] var i = 0 Loading @@ -163,8 +148,7 @@ internal class TraceStorage(internal var data: TraceData?) { i++ } } return if (::continuationIds.isInitialized && n < continuationIds.size) continuationIds[n] else 0 return continuationIds?.let { if (n < it.size) it[n] else null } ?: 0 } } Loading Loading
tracinglib/benchmark/src/ThreadLocalMicroBenchmark.kt +2 −2 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ import android.platform.test.flag.junit.SetFlagsRule import android.platform.test.rule.EnsureDeviceSettingsRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags import com.android.systemui.Flags.FLAG_COROUTINE_TRACING import java.util.concurrent.atomic.AtomicInteger import org.junit.After import org.junit.Assert Loading @@ -33,7 +33,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(Flags.FLAG_COROUTINE_TRACING) @EnableFlags(FLAG_COROUTINE_TRACING) class ThreadLocalMicroBenchmark { @get:Rule val setFlagsRule = SetFlagsRule() Loading
tracinglib/benchmark/src/TraceContextMicroBenchmark.kt +2 −2 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import androidx.test.filters.SmallTest import com.android.app.tracing.coroutines.createCoroutineTracingContext import com.android.app.tracing.coroutines.nameCoroutine import com.android.app.tracing.coroutines.traceCoroutine import com.android.systemui.Flags import com.android.systemui.Flags.FLAG_COROUTINE_TRACING import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking Loading @@ -41,7 +41,7 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) @EnableFlags(Flags.FLAG_COROUTINE_TRACING) @EnableFlags(FLAG_COROUTINE_TRACING) class TraceContextMicroBenchmark { @get:Rule val setFlagsRule = SetFlagsRule() Loading
tracinglib/core/src/coroutines/CoroutineTracing.kt +21 −9 Original line number Diff line number Diff line Loading @@ -19,7 +19,6 @@ package com.android.app.tracing.coroutines import com.android.app.tracing.traceSection import com.android.systemui.Flags import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract Loading Loading @@ -223,10 +222,14 @@ public inline fun <T, R> R.traceCoroutine(crossinline spanName: () -> String, bl // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the // coroutine resumes when tracing is active, we won't know its name. try { if (Flags.coroutineTracing()) traceThreadLocal.get()?.beginCoroutineTrace(spanName()) if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.beginCoroutineTrace(spanName()) } return block() } finally { if (Flags.coroutineTracing()) traceThreadLocal.get()?.endCoroutineTrace() if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.endCoroutineTrace() } } } Loading @@ -239,10 +242,14 @@ public inline fun <T> traceCoroutine(crossinline spanName: () -> String, block: // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the // coroutine resumes when tracing is active, we won't know its name. try { if (Flags.coroutineTracing()) traceThreadLocal.get()?.beginCoroutineTrace(spanName()) if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.beginCoroutineTrace(spanName()) } return block() } finally { if (Flags.coroutineTracing()) traceThreadLocal.get()?.endCoroutineTrace() if (com.android.systemui.Flags.coroutineTracing()) { traceThreadLocal.get()?.endCoroutineTrace() } } } Loading @@ -259,9 +266,10 @@ public inline fun <T> traceCoroutine(spanName: String, block: () -> T): T { } /** * Returns the passed context if [Flags.coroutineTracing] is false. Otherwise, returns a new context * by adding [CoroutineTraceName] to the given context. The [CoroutineTraceName] in the passed * context will take precedence over the new [CoroutineTraceName]. * Returns the passed context if [com.android.systemui.Flags.coroutineTracing] is false. Otherwise, * returns a new context by adding [CoroutineTraceName] to the given context. The * [CoroutineTraceName] in the passed context will take precedence over the new * [CoroutineTraceName]. */ @PublishedApi internal inline fun addName( Loading @@ -269,7 +277,11 @@ internal inline fun addName( context: CoroutineContext, ): CoroutineContext { contract { callsInPlace(spanName, InvocationKind.AT_MOST_ONCE) } return if (Flags.coroutineTracing()) CoroutineTraceName(spanName()) + context else context return if (com.android.systemui.Flags.coroutineTracing()) { CoroutineTraceName(spanName()) + context } else { context } } @PublishedApi Loading
tracinglib/core/src/coroutines/TraceContextElement.kt +9 −9 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import android.os.PerfettoTrace import android.os.SystemProperties import android.os.Trace import android.util.Log import com.android.systemui.Flags import java.lang.StackWalker.StackFrame import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.atomic.AtomicInteger Loading Loading @@ -60,10 +59,6 @@ internal object DebugSysProps { @JvmField val alwaysEnableContinuationCounting = SystemProperties.getBoolean("debug.coroutine_tracing.count_continuations_override", false) @JvmField val UsePerfettoSdk = SystemProperties.getBoolean("debug.coroutine_tracing.use_perfetto_sdk", false) } /** Loading Loading @@ -125,7 +120,7 @@ public fun createCoroutineTracingContext( walkStackForDefaultNames: Boolean = false, shouldIgnoreClassName: ((String) -> Boolean)? = null, ): CoroutineContext { return if (Flags.coroutineTracing()) { return if (com.android.systemui.Flags.coroutineTracing()) { TraceContextElement( name = name, isRoot = true, Loading Loading @@ -166,7 +161,11 @@ public fun nameCoroutine(name: String): CoroutineContext = nameCoroutine { name @Deprecated("Use .launchInTraced, .launchTraced, .shareInTraced, etc.") public inline fun nameCoroutine(name: () -> String): CoroutineContext { contract { callsInPlace(name, InvocationKind.AT_MOST_ONCE) } return if (Flags.coroutineTracing()) CoroutineTraceName(name()) else EmptyCoroutineContext return if (com.android.systemui.Flags.coroutineTracing()) { CoroutineTraceName(name()) } else { EmptyCoroutineContext } } private object PerfettoTraceConfig { Loading @@ -174,7 +173,7 @@ private object PerfettoTraceConfig { @JvmField val COROUTINE_CATEGORY: PerfettoTrace.Category = PerfettoTrace.Category("cc") init { if (DebugSysProps.UsePerfettoSdk) { if (android.os.Flags.perfettoSdkTracingV2()) { COROUTINE_CATEGORY.register() } } Loading Loading @@ -275,7 +274,8 @@ internal class TraceContextElement( // Don't use Perfetto SDK when inherited trace prefixes are used since it is a feature only // intended for testing, and only the `android.os.Trace` APIs currently have test shadows: private val usePerfettoSdk = DebugSysProps.UsePerfettoSdk && inheritedTracePrefix == null private val usePerfettoSdk = android.os.Flags.perfettoSdkTracingV2() && inheritedTracePrefix == null private var continuationId = if (usePerfettoSdk) nextRandomInt() else 0 Loading
tracinglib/core/src/coroutines/TraceData.kt +16 −32 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ package com.android.app.tracing.coroutines import android.os.Trace import com.android.app.tracing.beginSlice import com.android.app.tracing.endSlice import com.android.systemui.Flags import java.util.ArrayDeque import kotlin.contracts.ExperimentalContracts import kotlin.math.max Loading @@ -39,7 +38,7 @@ private typealias TraceSection = String @PublishedApi internal class TraceDataThreadLocal : ThreadLocal<TraceStorage?>() { override fun initialValue(): TraceStorage? { return if (Flags.coroutineTracing()) { return if (com.android.systemui.Flags.coroutineTracing()) { TraceStorage(null) } else { null Loading Loading @@ -69,20 +68,7 @@ internal class TraceStorage(internal var data: TraceData?) { * * `>1` indicates the current coroutine is resumed inside another coroutine, e.g. due to an * unconfined dispatcher or [UNDISPATCHED] launch. */ internal var contIndex = -1 internal lateinit var continuationIds: IntArray private lateinit var debugCounterTrack: String init { if (DebugSysProps.UsePerfettoSdk) { continuationIds = IntArray(INITIAL_THREAD_LOCAL_STACK_SIZE) } if (DEBUG) { debugCounterTrack = "TCE#${Thread.currentThread().threadId()}" } } private var contIndex = -1 /** * Count of slices opened on the current thread due to current [TraceData] that must be closed Loading @@ -94,7 +80,14 @@ internal class TraceStorage(internal var data: TraceData?) { * it indicates there is already something very wrong with the trace, so we will not waste CPU * cycles error checking. */ internal var openSliceCount = ByteArray(INITIAL_THREAD_LOCAL_STACK_SIZE) private var openSliceCount = ByteArray(INITIAL_THREAD_LOCAL_STACK_SIZE) private var continuationIds: IntArray? = if (android.os.Flags.perfettoSdkTracingV2()) IntArray(INITIAL_THREAD_LOCAL_STACK_SIZE) else null private val debugCounterTrack: String? = if (DEBUG) "TCE#${Thread.currentThread().threadId()}" else null /** * Adds a new trace section to the current trace data. The slice will be traced on the current Loading Loading @@ -129,32 +122,24 @@ internal class TraceStorage(internal var data: TraceData?) { fun updateDataForContinuation(contextTraceData: TraceData?, contId: Int) { data = contextTraceData val n = ++contIndex if (DEBUG) { Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack, n) } if (DEBUG) Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack!!, n) if (n < 0 || MAX_THREAD_LOCAL_STACK_SIZE <= n) return // fail-safe var size = openSliceCount.size if (n >= size) { size = max(2 * size, MAX_THREAD_LOCAL_STACK_SIZE) openSliceCount = openSliceCount.copyInto(ByteArray(size)) if (::continuationIds.isInitialized) { continuationIds = continuationIds.copyInto(IntArray(size)) } continuationIds = continuationIds?.copyInto(IntArray(size)) } openSliceCount[n] = data?.beginAllOnThread() ?: 0 if (::continuationIds.isInitialized && 0 < contId) { continuationIds[n] = contId } if (0 < contId) continuationIds?.set(n, contId) } /** Update [data] for suspension */ fun restoreDataForSuspension(oldState: TraceData?): Int { data = oldState val n = contIndex-- if (DEBUG) { Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack, n) } if (n < 0 || MAX_THREAD_LOCAL_STACK_SIZE <= n) return 0 // fail-safe if (DEBUG) Trace.traceCounter(Trace.TRACE_TAG_APP, debugCounterTrack!!, n) if (n < 0 || openSliceCount.size <= n) return 0 // fail-safe if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) { val lastState = openSliceCount[n] var i = 0 Loading @@ -163,8 +148,7 @@ internal class TraceStorage(internal var data: TraceData?) { i++ } } return if (::continuationIds.isInitialized && n < continuationIds.size) continuationIds[n] else 0 return continuationIds?.let { if (n < it.size) it[n] else null } ?: 0 } } Loading