Choreographer クラスによる FPS 計測
Android の Choreographer クラスを使用すると、フレームの描画開始のタイミングで呼び出されるコールバック (Choreographer.FrameCallback) を登録することができます。
Choreographer#postFrameCallback(callback: Choreographer.FrameCallback!)
上記のメソッドでコールバックを登録すると、次のフレーム描画のタイミングで doFrame(long frameTimeNanos)
メソッドが呼び出されます。
Choreographer.FrameCallback#doFrame(frameTimeNanos: Long)
パラメータとして描画開始時刻(ナノ秒単位)が渡されるため、前回のコールバック時の描画開始時刻からの差分を取れば、1 フレームの描画にかかった時間を求めることができます。 この値を使えば、FPS (Frame per second) は下記のように計算できます。
FPS = 1秒あたりのナノ秒 / 描画にかかった時間(ナノ秒)
サンプルコード
Fps クラスの実装
下記の Fps
クラスは、FPS を簡単に計測するためのクラスです。
内部で Android の Choreographer
を使っています。
Choreographer#postFrameCallback()
で登録したコールバックは、一度しか呼び出されないことに注意してください。
連続してフレーム描画のタイミングを取得するには、毎回同じコールバックを登録し直す必要があります(上記では、doFrame()
メソッドの先頭で登録しています)。
Fps クラスの使用例
Fps
クラスを使って FPS の観測を行うには、例えば次のようにします。
Fps().startObserving { fps ->
Log.i("DEBUG", "FPS = %.3f".format(fps))
}
(応用) 1 秒おきに平均 FPS を求める
上記のサンプルコードでは、毎フレーム FPS を求めてコールバック関数を呼び出していましたが、これでは高頻度すぎるという場合は、下記のようにすれば約 1 秒ごとに呼び出すように軽量化できます。
FrameCallback.doFrame()
が呼び出されたときに、前回のコールバックから 1 秒以上経過している場合だけ、コールバックするようにしています。
ここでは、約 1 秒間のフレーム数を数えて平均 FPS を求めています。
(応用) 1 秒おきに最低 FPS を求める
上記の例では、1 秒間の描画フレーム数を数えることで秒間平均 FPS を求めていましたが、その方法だと、あるフレームが非常に遅くても、残りのフレームが高速であれば、FPS としては比較的高い値が出てしまいます。
ここでは、もっとストイックに、過去 1 秒間で最も時間のかかったフレームの描画時間をもとに、FPS 計算するようにしてみます。 つまり、 秒間最低 FPS(秒間最悪 FPS) です。
秒間最低FPS = 1秒あたりのns / 最も時間のかかったフレームの描画時間(ns)