Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b1045087 authored by Steve Elliott's avatar Steve Elliott
Browse files

[kairos] reuse EvalScope to avoid reallocs

Flag: com.android.systemui.status_bar_mobile_icon_kairos
Bug: 383172066
Test: atest
Change-Id: I61c1cfda4390494f74dc058503c8b4c310b26626
parent fa8785aa
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -28,10 +28,8 @@ import com.android.systemui.kairos.internal.util.logDuration
internal typealias MuxResult<W, K, V> = MapK<W, K, PullNode<V>>

/** Base class for muxing nodes, which have a (potentially dynamic) collection of upstream nodes. */
internal sealed class MuxNode<W, K, V>(
    val lifecycle: MuxLifecycle<W, K, V>,
    protected val storeFactory: MutableMapK.Factory<W, K>,
) : PushNode<MuxResult<W, K, V>> {
internal sealed class MuxNode<W, K, V>(val lifecycle: MuxLifecycle<W, K, V>) :
    PushNode<MuxResult<W, K, V>> {

    lateinit var upstreamData: MutableMapK<W, K, PullNode<V>>
    lateinit var switchedIn: MutableMapK<W, K, BranchNode>
@@ -268,8 +266,6 @@ internal sealed class MuxNode<W, K, V>(
    }
}

internal typealias BranchNode<W, K, V> = MuxNode<W, K, V>.BranchNode

/** Tracks lifecycle of MuxNode in the network. Essentially a mutable ref for MuxLifecycleState. */
internal class MuxLifecycle<W, K, V>(var lifecycleState: MuxLifecycleState<W, K, V>) :
    EventsImpl<MuxResult<W, K, V>> {
+1 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ internal class MuxDeferredNode<W, K, V>(
    lifecycle: MuxLifecycle<W, K, V>,
    val spec: MuxActivator<W, K, V>,
    factory: MutableMapK.Factory<W, K>,
) : MuxNode<W, K, V>(lifecycle, factory) {
) : MuxNode<W, K, V>(lifecycle) {

    val schedulable = Schedulable.M(this)
    var patches: NodeConnection<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>>? = null
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ internal class MuxPromptNode<W, K, V>(
    lifecycle: MuxLifecycle<W, K, V>,
    private val spec: MuxActivator<W, K, V>,
    factory: MutableMapK.Factory<W, K>,
) : MuxNode<W, K, V>(lifecycle, factory) {
) : MuxNode<W, K, V>(lifecycle) {

    var patchData: Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>? = null
    var patches: PatchNode? = null
+16 −13
Original line number Diff line number Diff line
@@ -135,17 +135,18 @@ internal class Network(val coroutineScope: CoroutineScope, val coalescingPolicy:
                val e = epoch
                val duration = measureTime {
                    logLn(0, "===starting transaction $e===")
                    val evalScope = EvalScopeImpl(networkScope = this, deferScope = deferScopeImpl)
                    try {
                        logDuration(1, "init actions") {
                            // Run all actions
                            evalScope {
                            runThenDrainDeferrals {
                                for (action in actions) {
                                    action.started(evalScope = this@evalScope)
                                    action.started(evalScope)
                                }
                            }
                        }
                        // Step through the network
                        doTransaction(1)
                        doTransaction(evalScope, logIndent = 1)
                    } catch (e: Exception) {
                        // Signal failure
                        while (actions.isNotEmpty()) {
@@ -183,25 +184,27 @@ internal class Network(val coroutineScope: CoroutineScope, val coalescingPolicy:
            onResult.invokeOnCompletion { job.cancel() }
        }

    inline fun <R> evalScope(block: EvalScope.() -> R): R =
        block(EvalScopeImpl(networkScope = this, deferScope = deferScopeImpl)).also {
            deferScopeImpl.drainDeferrals()
        }
    inline fun <R> runThenDrainDeferrals(block: () -> R): R =
        block().also { deferScopeImpl.drainDeferrals() }

    /** Performs a transactional update of the Kairos network. */
    private fun doTransaction(logIndent: Int) {
    private fun doTransaction(evalScope: EvalScope, logIndent: Int) {
        // Traverse network, then run outputs
        logDuration(logIndent, "traverse network") {
            do {
                val numNodes =
                    logDuration("drainEval") { scheduler.drainEval(currentLogIndent, this@Network) }
                val numNodes: Int =
                    logDuration("drainEval") {
                        scheduler.drainEval(currentLogIndent, this@Network, evalScope)
                    }
                logLn("drained $numNodes nodes")
            } while (logDuration("evalOutputs") { evalScope { evalFastOutputs(this) } })
            } while (
                logDuration("evalOutputs") { runThenDrainDeferrals { evalFastOutputs(evalScope) } }
            )
        }
        coroutineScope.launch { evalLaunchedOutputs() }
        // Update states
        logDuration(logIndent, "update states") {
            evalScope { evalStateWriters(currentLogIndent, this) }
            runThenDrainDeferrals { evalStateWriters(currentLogIndent, evalScope) }
        }
        // Invalidate caches
        // Note: this needs to occur before deferred switches
@@ -209,7 +212,7 @@ internal class Network(val coroutineScope: CoroutineScope, val coalescingPolicy:
        epoch++
        // Perform deferred switches
        logDuration(logIndent, "evalMuxMovers") {
            evalScope { evalMuxMovers(currentLogIndent, this) }
            runThenDrainDeferrals { evalMuxMovers(currentLogIndent, evalScope) }
        }
        // Compact depths
        logDuration(logIndent, "compact") {
+3 −3
Original line number Diff line number Diff line
@@ -38,12 +38,12 @@ internal class SchedulerImpl(private val enqueue: (MuxNode<*, *, *>) -> Boolean)
        schedule(Int.MIN_VALUE + indirectDepth, node)
    }

    internal fun drainEval(logIndent: Int, network: Network): Int =
    internal fun drainEval(logIndent: Int, network: Network, evalScope: EvalScope): Int =
        drain(logIndent) { runStep ->
            runStep { muxNode ->
                network.evalScope {
                network.runThenDrainDeferrals {
                    muxNode.markedForEvaluation = false
                    muxNode.visit(currentLogIndent, this)
                    muxNode.visit(currentLogIndent, evalScope)
                }
            }
            // If any visited MuxPromptNodes had their depths increased, eagerly propagate those