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

Commit 04bf757e authored by Omar Miatello's avatar Omar Miatello
Browse files

Measure performance of MotionValues 1/2

Microbenchmark allow us to measure the performance of the Motion
Mechanics components

See: https://developer.android.com/topic/performance/benchmarking/microbenchmark-overview

This initial setup will establish a baseline for future testing and
improvements.

Tests were conducted on a Pixel 6 Pro with a locked clock (the most
reliable method for stable performance) and using the latest build of
the main branch.

See: https://developer.android.com/topic/performance/benchmarking/microbenchmark-overview#lock-clocks

Test: atest MotionValueBenchmark
Test: launched MotionValueBenchmark in Android Studio
Test: test_gradle_build.sh
Bug: 384402480
Flag: NONE benchmark module for Motion Mechanics
Change-Id: If1c41bbb666a882f7d2879d7cd528d2a3708b88d
parent 745ad89c
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!--
      Important: disable debugging for accurate performance results

      In a com.android.library project, this flag must be disabled from this
      manifest, as it is not possible to override this flag from Gradle.
    -->
    <application
        android:debuggable="false"
        tools:ignore="HardcodedDebugMode"
        tools:replace="android:debuggable" />
</manifest>
 No newline at end of file
+37 −0
Original line number Diff line number Diff line
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-dontobfuscate

-ignorewarnings

-keepattributes *Annotation*

-dontnote junit.framework.**
-dontnote junit.runner.**

-dontwarn androidx.test.**
-dontwarn org.junit.**
-dontwarn org.hamcrest.**
-dontwarn com.squareup.javawriter.JavaWriter

-keepclasseswithmembers @org.junit.runner.RunWith public class *
 No newline at end of file
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.mechanics.benchmark

import androidx.benchmark.junit4.BenchmarkRule
import androidx.benchmark.junit4.measureRepeated
import androidx.compose.runtime.mutableFloatStateOf
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.mechanics.DistanceGestureContext
import com.android.mechanics.MotionValue
import com.android.mechanics.spec.InputDirection
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

/** Benchmark, which will execute on an Android device. Previous results: go/mm-microbenchmarks */
@RunWith(AndroidJUnit4::class)
class MotionValueBenchmark {
    @get:Rule val benchmarkRule = BenchmarkRule()

    @Test
    fun createMotionValue() {
        val gestureContext = DistanceGestureContext(0f, InputDirection.Max, 2f)
        val currentInput = { 0f }
        benchmarkRule.measureRepeated { MotionValue(currentInput, gestureContext) }
    }

    @Test
    fun changeInput_readOutput() {
        val gestureContext = DistanceGestureContext(0f, InputDirection.Max, 2f)
        val a = mutableFloatStateOf(0f)
        val motionValue = MotionValue(a::floatValue, gestureContext)

        benchmarkRule.measureRepeated {
            runWithMeasurementDisabled { a.floatValue += 1f }
            motionValue.floatValue
        }
    }

    @Test
    fun readOutputMultipleTimes() {
        val gestureContext = DistanceGestureContext(0f, InputDirection.Max, 2f)
        val a = mutableFloatStateOf(0f)
        val motionValue = MotionValue(a::floatValue, gestureContext)

        benchmarkRule.measureRepeated {
            runWithMeasurementDisabled {
                a.floatValue += 1f
                motionValue.output
            }
            motionValue.output
        }
    }

    @Test
    fun readOutputMultipleTimesMeasureAll() {
        val gestureContext = DistanceGestureContext(0f, InputDirection.Max, 2f)
        val currentInput = mutableFloatStateOf(0f)
        val motionValue = MotionValue(currentInput::floatValue, gestureContext)

        benchmarkRule.measureRepeated {
            currentInput.floatValue += 1f
            motionValue.output
            motionValue.output
        }
    }
}