Benchmarks im Bereich Continuous Integration

Mit Continuous Integration (CI) können Sie Benchmarks ausführen, um die Leistung Zeit einplanen und Leistungsrückgänge oder -verbesserungen erkennen Ihre App veröffentlicht. Diese Seite enthält grundlegende Informationen zum Benchmarking auf CI.

Bevor Sie mit dem Benchmarking in CI beginnen, sollten Sie sich überlegen, wie Erfassung und die Auswertungsergebnisse sich von regulären Tests unterscheiden.

Unscharfe Ergebnisse

Auch wenn es sich bei Benchmarks um instrumentierte Tests handelt, sind die Ergebnisse nicht nur bestanden oder nicht bestanden. Benchmarks liefern Zeitmessungen für das Gerät, auf dem sie ausgeführt werden. Wenn Sie die Ergebnisse im Zeitverlauf grafisch darstellen, können Sie Änderungen im Zeitverlauf beobachten und Rauschen beobachten. Messsystem verwendet werden.

Echte Geräte verwenden

Benchmarks auf physischen Android-Geräten ausführen Sie können zwar auf Emulatoren, wird davon abgeraten, da sie kein realistisches Bild Nutzererfahrung und liefert stattdessen Zahlen, die mit dem Betriebssystem und der Hardware des Hosts verknüpft sind. Funktionen. Verwenden Sie echte Geräte oder einen Dienst, mit dem Sie Tests durchführen können. auf echten Geräten wie dem Firebase Test Lab.

Benchmarks ausführen

Die Ausführung der Benchmarks im Rahmen Ihrer CI-Pipeline kann sich von der Ausführung unterscheiden lokal von Android Studio. In der Regel führen Sie die Android-Version Integrationstests mit einer Gradle-connectedCheck-Aufgabe durchführen. Diese Aufgabe wird automatisch erstellt Ihr APK und Ihr Test-APK und führt die Tests auf den Geräten aus, die mit den CI-Server. Bei der Ausführung in CI muss dieser Ablauf normalerweise in verschiedenen Phasen.

Eine Community

Führen Sie für die MicroBenchmark-Bibliothek die Gradle-Task aus. assemble[VariantName]AndroidTest, wodurch dein Test-APK erstellt wird, das Folgendes enthält: sowohl Ihren Anwendungscode als auch den getesteten Code.

Alternativ müssen Sie für die MacroBenchmark-Bibliothek Ihr Ziel-APK erstellen und Test-APK separat. Führen Sie daher :app:assemble[VariantName] aus und :macrobenchmark:assemble[VariantName] Gradle-Aufgaben.

Installieren und ausführen

Diese Schritte werden in der Regel ausgeführt, ohne dass Gradle-Aufgaben ausgeführt werden müssen. Beachten Sie, dass sie kann abstrahiert sein, je nachdem, ob Sie einen Dienst verwenden, mit dem Sie Tests auf echten Geräten.

Verwende für die Installation den Befehl adb install und gib das Test-APK an oder das Ziel-APK.

Führen Sie den Befehl adb shell am aus, um alle Benchmarks auszuführen:

adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Verwenden Sie bei Verwendung der MacroBenchmark-Bibliothek androidx.test.runner.AndroidJUnitRunner als Instrumentierungs-Runner.

Sie können dieselben Instrumentierungsargumente wie in der Gradle-Konfiguration übergeben. mit dem Argument -e. Informationen zu allen Optionen für Instrumentierungsargumente finden Sie unter MicroBenchmark-Instrumentierungsargumente oder Instrumentierungsargumente für MacroBenchmark hinzufügen

Sie können z. B. das Argument dryRunMode so festlegen, dass MicroBenchmarks wie folgt ausgeführt werden: Teil Ihres Überprüfungsprozesses für Pull-Anfragen. Wenn dieses Flag aktiviert ist, MicroBenchmarks werden nur in einer einzigen Schleife ausgeführt, um zu gewährleisten, dass sie ausgeführt werden. korrekt, aber die Ausführung dauert nicht zu lange.

adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Weitere Informationen zur Ausführung Instrumentierungstests über die Befehlszeile finden Sie unter Tests mit ADB ausführen.

Uhren sperren

Das MicroBenchmark-Gradle-Plug-in bietet den Befehl ./gradlew lockClocks, um die CPU-Uhr eines gerooteten Geräts zu sperren. Dies ist nützlich, um die Stabilität wenn Sie Zugriff auf gerootete Geräte haben, z. B. „userdebug“ baut. Sie können replizieren Sie dies mit dem Shell-Skript lockClocks.sh, das im Quelle der Bibliothek

Sie können das Skript entweder direkt auf einem Linux- oder Mac-Host ausführen oder mit einigen ADB-Befehlen an das Gerät:

adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh
adb shell /data/local/tmp/lockClocks.sh
adb shell rm /data/local/tmp/lockClocks.sh

Wenn Sie das Shell-Skript direkt auf einem Host ausführen, ein verbundenes Gerät.

Weitere Informationen darüber, warum es hilfreich ist, die CPU-Uhren zu sperren, finden Sie unter konsistente Benchmarks zu erhalten.

Ergebnisse erfassen

Die Benchmarking-Bibliotheken geben Messungen in JSON zusammen mit Trace-Profilen für ein Verzeichnis auf Android-Gerät nach jedem Benchmark-Lauf. MacroBenchmark gibt mehrere Perfetto-Trace-Dateien aus: eine pro gemessener Iteration von jeder MacrobenchmarkRule.measureRepeated-Schleife. Mit einem Mikro-Benchmark wird dagegen nur eine Trace-Datei für alle Iterationen jedes BenchmarkRule.measureRepeated Trace-Dateien zur Profilerstellung werden ebenfalls an in dasselbe Verzeichnis.

Dateien speichern und ausfindig machen

Wenn Sie die Benchmarks mit Gradle ausführen, werden diese Dateien automatisch im Output-Verzeichnis Ihres Hostcomputers build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/

Wenn Sie die Datei direkt mit dem Befehl adb ausführen, müssen Sie die Dateien abrufen. manuell. Standardmäßig werden die Berichte auf dem Gerät im Medienverzeichnis der externen Speicher der getesteten App. Der Einfachheit halber gibt die Bibliothek den Pfad aus. der Datei in Logcat ein. Beachten Sie, dass der Ausgabeordner je nach auf welcher Android-Version die Benchmarks ausgeführt werden.

Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

Sie können auch festlegen, wo Benchmarkberichte auf der Seite Gerät mit dem Instrumentierungsargument additionalTestOutputDir Dieses Ordner muss von Ihrer App beschreibbar sein.

adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner

Unter Android 10 (API-Level 29) und höher werden die Tests Ihrer App in einem Speicher ausgeführt Sandbox, die verhindert, dass Ihre App auf Dateien außerhalb des App-spezifischen Verzeichnisses. Um Dateien in einem globalen Verzeichnis speichern zu können, z. B. Übergeben Sie als /sdcard/Download die folgende Instrumentierung Argument:

-e no-isolated-storage true

Außerdem müssen Sie Legacy-Speicheroptionen im Manifest:

<application android:requestLegacyExternalStorage="true" ... >

Weitere Informationen Speicherplatz.

Dateien abrufen

Um die generierten Dateien vom Gerät abzurufen, verwende die adb pull , der die angegebene Datei in das aktuelle Verzeichnis auf Ihrem Host abruft:

adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json

Um alle benchmarkData aus einem bestimmten Ordner abzurufen, aktivieren Sie die folgendes Snippet:

# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull

Die Trace-Dateien (.trace oder .perfetto-trace) werden im selben als benchmarkData.json. Sie können sie also auf dieselbe Weise erfassen.

Beispiel für Benchmarkdaten

Die Benchmark-Bibliotheken generieren JSON-Dateien mit Informationen über die und die tatsächlichen Benchmarks, auf denen sie ausgeführt wurde. Die folgendes Snippet repräsentiert die generierte JSON-Datei:

{
    "context": {
        "build": {
            "brand": "google",
            "device": "blueline",
            "fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
            "model": "Pixel 3",
            "version": {
                "sdk": 31
            }
        },
        "cpuCoreCount": 8,
        "cpuLocked": false,
        "cpuMaxFreqHz": 2803200000,
        "memTotalBytes": 3753299968,
        "sustainedPerformanceModeEnabled": false
    },
    "benchmarks": [
        {
            "name": "startup",
            "params": {},
            "className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
            "totalRunTimeNs": 4975598256,
            "metrics": {
                "timeToInitialDisplayMs": {
                    "minimum": 347.881076,
                    "maximum": 347.881076,
                    "median": 347.881076,
                    "runs": [
                        347.881076
                    ]
                }
            },
            "sampledMetrics": {},
            "warmupIterations": 0,
            "repeatIterations": 3,
            "thermalThrottleSleepSeconds": 0
        }
    ]
}

Weitere Informationen