Flutter-タイマーアプリケーションを作ってみる6

使っていて不具合があったのでその修正を行ったついでに、タイマー実行画面の実行速度に関するパフォーマンスチューニングをやってみた。
この内容はGithubにプッシュしてある。

現在の状況

計測方法

基本的には以下のページ以降に書かれているものを参考に実施していった。

Improving rendering performance
How to measure and evaluate your app's rendering performance.

上記ページにはprofileモードで計測してくださいと書かれているのだけど、実機はprofileモードが使えるのだがシミュレーターは使えないので、デバッグモードでの計測になってしまっている。

CPH2099

UIスレッドに関しては問題ないようなのだけどRasterスレッドに関しては60FPS(17ms)以内に納まっておらず最大で35ms位かかっている。

作ったタイマーアプリのデータ更新頻度は100msなのでそれには間に合ってはいるのだけど。

シミュレーター

通常のデバッグモードでのプロファイルなので参考程度の情報になるかな。

シミュレーターでも実機より早いんだなというのがよくわかる。
一応、60FPS(17ms)以内にUIもRasterも処理がほぼすべて終わっている。

改善点

これだけちっちゃく簡単なアプリだとあまり改善点はないのだけど、それでもいくつかざっとわかる範囲で対応していった。

本来はプロファイルした結果からボトルネックを絞り出して改善内容を見つけるのだろうけど、はっきり言ってプロファイル情報からボトルネックを抽出するのことはできなかった。

Raster側の情報を見ようと、図の赤い部分を選択すると以下の様な詳細情報が出てくる。


分からん。

ということでDebug文やAndroid Studio側のウィジェットの更新頻度を見るツールを使って不必要に更新がされている箇所がないかを調べてみた。

Lapの更新頻度

プログラムの時間の更新頻度は100msにしている。その際に開始時間との差を現在の時刻として計算し、タイマーの残時間をTextとして表示するようにしている。
その処理行っているのがTimerControlVM::currentTime。

このセッターが呼び出されるのは先に書いた通り100ms単位なのだが、残時間の単位は秒。
そのため実際の残時間の更新は10回に1回の割合でしか行っていないことになる。

ウィジェットの更新頻度を見ても、そうなっていた。

そこで、この部分前回の残時間と新しい残時間の文字列が異なったら更新するというような処理に変更してみた。


残念ながら、実機では差がなかった。


こちらはシミュレーター。若干UIが短くなったかなという程度。

CustomPaintの更新頻度

タイマーの柄の部分をCustomPaintの前景・背景の2つのCustomPainterを使って描画しているのだけど、この部分100ms単位に両方描画処理が走ってしまっている。
背景側は外側の設定時間を表す円弧なので、この部分は100ms単位に走らなくてもいいのだけど。

これに関して調べたところ、前景側のCustomPainterの処理が実行されるとそれに関連するウィジェットもどうやら更新されるらしく、これを制御するためにはRepaintBoundaryで更新するものをらっぷするという情報があった。

そこで、2つのCustomPaintをStackで配置して、内側のCustomPainter側をRepaintBoundaryでラッピングするようにしてみた。


実機でのRaster側の改善があったようだ。16ms以内に納まっているフレームが改訂前よりは多くなっている。以前は38FPSだったのが48FPSにまで改善している。


こちらはシミュレーター。う~んどうだろう。

Canvas.draw~の回数抑止

When CustomPainter needs to paint many complex paths in each frame, performance gets degraded when zooming or panning the CustomPaint widget · Issue #72066 · flutter/flutter
Please tell us exactly how to reproduce the problem you are running into: Create a CustomPaint object. Paint on it a num...

上の情報にあった対応を実施してみた。

タイマーの絵の部分はPathを作ってそのPathに対して塗りつぶしと外形描画の2種類を行っている。
塗り潰しに関しては塗り潰す色を設定する都合があるため1回の描画での対応はできないが、外形部分は複数のPathを合成し一回のCanvas.draw~に納めることができるので、その対応をして見た。


若干速くなっている気がしなくもないといった感じだろうか。


シミュレーション側。若干速くなっているのだろう。FPSが上がってるので。ただ17msに納まらない部分が多くなったような。

総合

3つの対応を行った。ただその単独の結果としてはそれぞれ微妙な感じだったのだけど、3つ組み合わせた結果を見てみた。


なぜかわからないけど、トータルとしてみた場合なぜかいい結果になってた。
対応前は40FSPを割ってたのけど、55FPSまで上がっている。


こちらはシミューレーターの結果。
分かりづらいけど、変更前に比べUI/Rasterともに処理時間が低下しているのが分かった。

結果

総合の内容を見る限り、3種類の対応を行うことで手持ちのパフォーマンスが悪い機種でも60FPSに近い値を出せたので、これを最終結果とした。

しかし、パフォーマンスチューニングツールの結果をもとにボトルネックを探して対応していくというWindowsで行ってきた手法が使えなかったのが意味不明なところ。やり方として間違ってるのだろうか。
チューニング方法に関してネット検索しても情報が出てこなかったので、手探りで行わなければいけないのだろうか。

なおウィジェットの更新頻度を調べるツールがAndroid Studioでしか使用できないのが何気に面倒。またこの情報を反映して、更新するウィジェットのチューニングをしても、今回のケースでは単一ではあまり効果がなかったのも残念だった。
ウィジェットが多い場合は効果があるんだろうか。

コメント

タイトルとURLをコピーしました