頭外音像定位アプリのプロジェクトにandroidx.benchmarkを導入してみた
これです
androidx.benchmark
は何となく気になっていたので、冬休みの間の宿題として、数年前に作ったあと放置していたリポジトリをほじくり返してこれに導入してみることにした。何をやっているのかは
にだいたい書いてある。今回はFFTをやっているところと、畳み込み演算をやっているところのベンチマークをとってみることにした。
今回のポイント
公式のドキュメントを参考にしながら、benchmarkモジュールを追加するやつをやった。
これ以外に、今回のプロジェクトで必要だった作業は次の二つ:
- サポートライブラリを使っていたのだが、benchmarkはandroidxのライブラリなのでjetifyした。
- シングルモジュールの構成になっていたのだが、benchmarkモジュールはlibraryモジュールなのでapplicationモジュールのプロジェクトに依存できない。ベンチマークをとりたいコードを別のモジュールに移した。
また、ドキュメントには./gradlew benchmark:connectedCheck
をやるとプロジェクトのoutputフォルダに測定結果ファイルがコピーされると書いてあるが、ver. 1.0.0ではコピーするタスク(benchmark:benchmarkReport
)で失敗する*1。結果ファイル自体は端末の外部ストレージに保存されているので自分でpullすればよい。
ベンチマークの測定結果と考察
ベンチマークの測定結果ファイルには、かかった時間の最大値、最小値、中央値、各イテレーションの実測値などが書いてある。また、ウォームアップの回数なんかもわかる。実際のファイルは上のPRに張り付けたので興味のある方は実際に見てみてほしい。
これによると、畳み込み演算の実行時間の中央値はFFTのものと比べて8倍程度になっている。想定では畳み込み演算の中でFFTは6回しかやっていないはずだし、なんなら内部的には畳み込み演算を並列に計算したりしているのだが、複素数の乗算や加算、スレッドの待ち合わせなどの分でFFTを2回余計にやるぐらいの時間がかかってしまっているというのがわかる。
もう少し詳しく見ていく必要はありそう*2だが、確かにFFTや畳み込み結果の待ち合わせ処理には改善の余地がありそうなので、アルゴリズムを見直したり、Kotlinのコルーチンを入れたりして様子を見ていきたい。
2019年に見たアニメ
いつものやつをやります。例によって50音順です。カッコ[]
付きは未視聴(録画消化待ち)です。今年は全体的にジャンプのアニメが強かったですね。
トルネの不調に泣かされた年でもあった。ほとんどのアニメを1クール遅れで視聴した*1のだがそのせいか円盤をほとんど買っていない*2ということに気が付いた。
冬クール
- えんどろ~!
- かぐや様は告らせたい~天才たちの恋愛頭脳戦~
- 賭ケグルイ××
- ケムリクサ
- けものフレンズ2
- 荒野のコトブキ飛行隊
- 同居人はひざ、時々、頭のうえ。
- どろろ
- ブギーポップは笑わない
- 魔法少女特殊戦あすか
- モブサイコ100 II
- 約束のネバーランド
- revisions リヴィジョンズ
- 私に天使が舞い降りた!
春クール
- アイドルマスター シンデレラガールズ劇場 CLIMAX SEASON
- 鬼滅の刃
- キャロル&チューズデイ
- この世の果てで恋を唄う少女YU-NO
- 消滅都市
- 進撃の巨人 Season3 Part.2
- ストライクウィッチーズ 501部隊発進しますっ!
- 世話やきキツネの仙狐さん
- ひとりぼっちの○○生活
- Fairy gone フェアリーゴーン
- 文豪ストレイドッグス 第3シーズン
- ワンパンマン(第2期)
夏クール
シャミ子が悪いんだよ、僕は何度か聞いたような気がしたんだけどなあ。
- 荒ぶる季節の乙女どもよ。
- かつて神だった獣たちへ
- コップクラフト
- 女子高生の無駄づかい
- 戦姫絶唱シンフォギアXV
- ソウナンですか?
- ダンベル何キロ持てる?
- 手品先輩
- Dr.STONE
- ヴィンランド・サガ
- BEM
- まちカドまぞく
- ロード・エルメロイⅡ世の事件簿 -魔眼蒐集列車 Grace note-
秋クール
- アズールレーン
- 神田川JET GIRLS
- 警視庁 特務部 特殊凶悪犯対策室 第七課 -トクナナ-
- スタンドマイヒーローズ PIECE OF TRUTH
- ノー・ガンズ・ライフ
- ハイスコアガール II
- BEASTARS
- Fairy gone フェアリーゴーン 第2クール
- Fate/Grand Order -絶対魔獣戦線バビロニア-
- 放課後さいころ倶楽部
- 僕のヒーローアカデミア
- ライフル・イズ・ビューティフル
映画
ここは大体公開順に並べています。プロメアはたぶん人生で初めて劇場に2回見に行った作品ということになった。
- 劇場版「幼女戦記」
- 劇場版総集編 メイドインアビス【前編】旅立ちの夜明
- 劇場版総集編 メイドインアビス【後編】放浪する黄昏
- ラブライブ!サンシャイン!! The School Idol Movie Over the Rainbow
- 劇場版シティーハンター <新宿プライベート・アイズ>
- 劇場版 響け!ユーフォニアム ~誓いのフィナーレ~
- ガールズ&パンツァー 最終章 第2話
- プロメア
- 海獣の子供
- ヴァイオレット・エヴァーガーデン 外伝 ‐永遠と自動手記人形‐
- 冴えない彼女の育てかた Fine
lottie-androidのgetCurrentKeyframe()の性能を改善するパッチが取り込まれた
モチベーション
BaseKeyframeAnimation.getCurrentKeyframe()
は、アニメーションのプログレス(0から1の実数で表されるアニメーションの進捗度合い)の値にあうKeyframe
を返すメソッド。このKeyframe
はsetProgress()
の際にキャッシュされている。処理のおおざっぱな流れは次の記事で書いた。
getCurrentKeyframe()
が呼ばれるたびに、キャッシュのヒット判定(現在のプログレスがKeyframe
の時間幅に含まれているかチェックする)メソッドが呼ばれたり、リストから探す処理が走ったりする。何をするにもこれが呼ばれる。一度のメソッド呼び出しで何度も呼ばれることがある。
BaseKeyframeAnimation
は0個以上のKeyframe
を持っているのだが、たかだか1個しか持っていない場合には現在のキーフレームをキャッシュしたりプログレスが範囲に入っているかを判定する必要がない(0個の時も言うまでもない)。そこで、0個の場合、1個の場合、それより多い場合とに分けて不要な処理を行わないようにした。
何をしたのか
BaseKeyframeAnimation
が持っているKeyframe
のリストをラップしてそれぞれの場合に適した処理を行う静的な内部クラスを実装した。具体的には、
- Keyframeが0個のときはなにもしない。
- Keyframeが1個のときはキャッシュせず、キャッシュのヒット判定も行わない。
- Keyframeが2個以上のときはこれまでと同じ処理をする。
Keyframe
を1個しか持たないアニメーション部品が多いほど効果が出る。Keyframeが0個の時というのはほとんどないので効果もほとんどない。メモリ使用量が若干増える影響はあるものの、メソッド呼び出し回数が減ったため処理時間はせいぜい3割程度短くなった(アニメーションの構成による)。また処理の見通しが多少は良くなった。
抽象クラスの処理の変更はそれを継承しているクラスにも影響が出るかもしれないので難しかった。テストがちゃんとあってよかった。さらに最適化できそうだが効果がうすそうだったのでやらなかった。キャッシュの仕方に若干不満が残ってしまったのでもっといい形を思いつけば置き換えたい。
余談
じつは性能計測用のトレースメソッドをR8で消すほうが効果があるかもしれなかったりする