パフォーマンスチューニングが必要になった理由
- プロジェクトでRedux Architectureを採用したが、求める機能に合致するライブラリがないためチーム内で自作した
pub.dev
- これにより求める機能が実装されたが、プロジェクトでは特定条件下でState更新が1000回 / 秒を超える場合がある
- UI = f(State)を愚直に実装していたため、Widget.build()が1000回 / 秒走ることとなり、パフォーマンスに明らかな悪影響が出た
解決方法
- Stateを流すためのStreamと、WidgetをビルドするためのStreamを分けた
- StateをハンドリングするためのStreamは取りこぼしがあってはならない(イベントハンドリングなど)ため、実装をそのままとした
- それとは別に、WidgetをビルドするためのStreamを追加した
- こちらは最大で60fpsでデータが流れる仕様となっているため、仮に1000回 / 秒State更新が走ってもWidgetに反映されるのは60回 / 秒が最大である
BehaviorSubject<TState> _initializeRenderStream(Duration renderingInterval) {
final result = BehaviorSubject<TState>.seeded(state);
_subscription.add(
Stream.periodic(
renderingInterval,
(computationCount) => state,
).distinct().listen(result.add),
);
return result;
}
- これによりWidget.build()のスパイクによる異常rebuildを回避してパフォーマンスが向上した