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で消すほうが効果があるかもしれなかったりする