androidx.benchmarkの1.0.0がリリースされたので試してみる
Android Dev Summit 2019の下記のセッションで軽くふれられていた androidx.benchmark
の1.0.0がリリースされたようなのでさわってみます。このセッションはbenchmarkの使い方を説明したものではないけど、色々と面白いのでおすすめです。
それではやっていきましょう。
0. Reference
Jetpack Benchmarkの公式referenceはこの辺り。
API referenceはこの辺り。
で、これらをどうやって使っていくかはこの辺りにまとまっています。
1. Benchmark用のmoduleを作る
最初に紹介した動画でも言及されていたのですが、benchmarkを測る時はdebug modeをOFFにすることが奨励されています。 こういったconfigurationを他のアプリのモジュールから分離するために専用のmoduleを作ります。
Android StudioはBenchmark moduleを作るためのtemplateが用意されているのでこれを利用します。ただし、Android Studio 3.5系を使っている場合はこのtempleteを使うためには手動で下記の設定が必要です。
Help
>Edit Custom Properties
をクリック。(「idea.propertiesのファイルが今ないから作る?」って聞かれたらCreate
を選択して下さい。)- 下記を1行追加してAndroid Studioを再起動する
npw.benchmark.template.module=true
で、ここからはAndroid Studio 3.6からと共通。Templateを使ってbenchmark moduleを用意します。
- Projectを右クリックして
New
>Module
を選択 - Moduleの選択肢が出てくるので
Benchmark Module
を選んでNext
をクリック - Module名とか色々変えたかったら変更して
Finish
をクリック
これでProject rootの下に benchmark
moduleが作成されます。
このmoduleの build.gradle
をみると androidx.benchmark:benchmark
にすでに依存が付いています。ただしtemplateで指定されたversionが古いままだったりする😇1.0.0 だとpackage nameも変わっているので注意です。下記に変えてやりましょう。
androidTestImplementation 'androidx.benchmark:benchmark-junit4:1.0.0'
また、gradleのsyncが下記のエラーで失敗したりする。
androidx.benchmark.AndroidBenchmarkRunner, in project benchmark, which is no longer valid as it has been moved to androidx.benchmark.junit4.AndroidBenchmarkRunner.
というわけで正しい依存をつけてエラーをとってやりましょう。
defaultConfig { - testInstrumentationRunner 'androidx.benchmark.AndroidBenchmarkRunner' + testInstrumentationRunner 'androidx.benchmark.junit4.AndroidBenchmarkRunner' }
また、このmoduleの androidTest
下に作られたAndroidStudioにはdebug modeをOFFにする設定がすでに記述されています。便利!
project_root/benchmark/src/androidTest/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.muumuu.benchmark"> <!-- 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>
2. benchmarkを書いていく
BenchmarkはInstrumentation testになります。benchmarkを作るには BenchmarkRule
クラスを使っていきます。余談ですが、このクラスにはいくつかサブクラスが存在していて、Activity用のbenchmarkを測りたい時は ActivityTestRule
と ctivityScenarioRule
を使うようです。 UIのbenchmarkを測る時は @UiThreadTest
アノテーションを使います。
今回はActivityを作るのが面倒だったのでdata processingでbenchmarkを測っていきます。最近同僚に教えてもらったちょうどいい記事があるのでこれを試します。
この記事の内容を軽く紹介すると、データサイズが大きい場合に、Kotlinの Iterable
と Sequence
だとdata processのstepが2以上ある場合はSequence
使ったほうが早いよーという話です。
こんな感じで 1から1000のlistを作ってSequence
とIterable
で全く同じ操作をしてそれぞれのbenchmarkを測ります。
@RunWith(AndroidJUnit4::class) class SequenceBenchmark { @get:Rule val benchmarkRule = BenchmarkRule() private val dataSet = (1..1000).toList() @Test fun logSequence() { benchmarkRule.measureRepeated { dataSet.asSequence() .filter { it.rem(2) == 0 } .map { it * 100 } .average() } } @Test fun logIteration() { benchmarkRule.measureRepeated { dataSet .filter { it.rem(2) == 0 } .map { it * 100 } .average() } } }
で、普通のtestを実行するようにtestを実行します。以下結果。確かにSequence
の方が早い。
Started running tests benchmark: 63,038 ns SequenceBenchmark.logSequence benchmark: 87,656 ns SequenceBenchmark.logIteration
感想
意外と簡単にシュッとできるので便利でした。Templeteがupdateされれば言うことない。
言いたいことは以上です。