Redux: 大規模ストアと頻繁な更新によるReduxのパフォーマンス

作成日 2016年01月28日  ·  18コメント  ·  ソース: reduxjs/redux

これは質問です/アドバイスを求めてください

多くのページ、パネル、サブパネルなどがたくさんあるので、状態がたくさんあるかなり大きなSPAがあるとしましょう。

ここで、(さまざまなレベルで)レデューサー構成を使用してアプリを設計し、ストアを非常によく整理して、作業を楽にすることを想像してみてください。

ここで、パネルの1つでライブイベントを取得するとします。 たとえば、証券取引所の値で構成される100個のアイテムのリストがあり、それぞれが1秒間に1回独立して更新されているとします。 (ネットワークの問題を無視し、値がランダムに生成されると想定してください)。

Reactはスマートで、必要のないときはレンダリングされないので、進むべき道だと思います。

しかし、Reduxでそれを機能させる方法がわかりません。

1つのストアを使用してすべての株価を取得し、それらを個別に保存してアクションなどをトリガーし、すべての情報が非常によく整理された非常に優れたストアを持つことができるのは素晴らしいことです。

しかし、私は非常に頻繁に更新を取得しているので、すべてのレデューサー(多くなります)を呼び出す必要があります。 ほとんどの場合、オブジェクトポインタのみをコピーするため、呼び出しは非常に高速になることを知っています。

とにかく、私のアプリは合成を非常に頻繁に使用しているので、多くの関数呼び出しがあります。 これは、特に古いモバイルデバイスでは悪い場合があります。

私はそのようなアプリの1つを設計していますが、Reduxをそこに適合させる方法がわかりません(可能な場合)。 おそらく、この時点でいくつかの貴重なアドバイスを与えることができます(私はちょうどそれに取り組み始めました)。 レデューサーへの呼び出しを最小限に抑えるために、(どういうわけか)異なるストアをそれぞれ異なるアクションにのみ接続して使用することは可能ですか?

何か案は?
ありがとう

discussion

最も参考になるコメント

React ReduxはforceUpdate()をまったく使用しません。 それははるかに注意深いです:-)
はい、不要な更新が発生することはありません。

全てのコメント18件

このコメントとディスカッション全体が役立つ場合があります: https

@sompylasarに感謝します。 私の質問は少し異なります。

更新された値はアプリの基本的な部分であるため、ストアに属していると確信しています。

このような店があるとしましょう:

store: {
  subStore1: {
    subSubstore1: {}
    ...
    subSubstore10: {}
  },
subStore2: {
    subSubstore1: {}
    ...
    subSubstore10: {}
  }
...
subStore10: {
    subSubstore1: {}
    ...
    subSubstore10: {}
  }
}

(私はあなたがアイデアを得ることを願っています)。 実際、これはさらに深くなる可能性があります。

すべてのサブストアはアプリの非常に異なる懸念事項に対応しており、サブサブストアは独自のレデューサーによって処理されます。

次に、substore2:{subSubstore6}のみを更新することがわかっているアクションをディスパッチします。

ポインタsubstore1、substore3、... substore9を単純にコピーして、他のsubSubstoreのレデューサーを呼び出してみませんか?

どういうわけかcombineReducersに、どの可能なアクションが子レデューサーの新しい状態をトリガーするかを伝えることは可能でしょうか?

または、別のストアの使用を検討する必要がありますか?

何かアドバイス?

ありがとう!

https://github.com/omnidan/redux-ignoreを確認することをお勧めし

私はreduxについて知りませんでした-無視してください、そしてそれは間違いなく非常に有望に見えます!

おそらくこれは、直交する懸念に対処する非常に大規模なアプリ(SPA)を開発するときに実行できる方法です。

アドバイスありがとうございます!

しかし、私は非常に頻繁に更新を取得しているので、すべてのレデューサー(多くなります)を呼び出す必要があります。

重要な修正をさせてください。Reduxストアにはレデューサー機能が1つしかありません。 その機能を好きなように分割して、必要に応じて利便性、速度、またはその他の要素とのトレードオフを行うことができます。 combineReducersはこれを処理する一般的な方法ですが、必須ではありません。

私が持っている潜在的にパフォーマンスの高いアイデアの1つは、タイプごとにキー設定されたハンドラーのオブジェクトにtypeをマップすることです。 これを行うための素朴な方法は次のとおりです。

function buildReducer(handlers) {
  return function reducer(state = initialState, action) {
    return handlers[action.type](state, action);
  }
}

その場合、タイプごとに1つのレデューサーのみを実行します。 アクションからレデューサーへの1:1マッピングがないため、タイプごとにレデューサーを減らす必要があるかもしれませんが、それでもオーバーヘッドの量を減らすことができます。

もちろん、DOM操作とReactレンダリングは、本番アプリの一部のプレーンJSよりも遅くなる可能性があります。 さらに、ほとんどのJSエンジンはレデューサーをホットコードとして扱い、JITはそれらをネイティブコードにコンパイルするので、実際にはそれほど遅くなるとは思いません。

redux-batched-subscribeを使用してレンダリングをデバウンスすることもできるため、非常に短い期間に複数のアクションがある場合、レンダリングは1回だけになります。

https://github.com/rackt/react-redux/issues/263を参照して

プッシュされたデータを受信する大規模なアプリの場合、データ構造は状態ツリーに存在する必要がありますか?
プッシュが毎秒起こっていたとしたら、私たちは何千もの州の歴史になってしまうでしょう? レデューサーがツリーのごく一部を変更しているだけであることは理解しています。

これの副作用は、devtools画面に多くのdom要素があり、すぐにブラウザの速度が低下することです。 使えなくなるところまで来ています。

これは正しい仮定ですか?

@jorgecarmonaこれは、

@timdorr同意しました。

では、実際のパフォーマンスに戻りましょう。 毎秒アプリにストリーミングされているデータを状態ツリーに蓄積する必要がありますか? このアプローチは拡張できますか?

配列に追加するだけで、スパースにならない場合は、そうする必要があります。 O(n)のパフォーマンスが発生する可能性がありますが、チェックポイントを設定してサブ配列に分割することで解決することもできます。 フロントエンドのDOMメンテナンスほど、それがボトルネックになるとは思いません。

@timdorrこれらの推奨事項を使用していくつかのテストを行います。

お時間を割いていただきありがとうございます!

@gaearon @timdorr react-ignoreは、一部のアクションで一部のレデューサーサブツリーをスキップするのに役立つため、状態ツリーの更新は最小限に抑えられます。
しかし、状態の変化にサブスクライブされているすべてのコンポーネントはどうでしょうか。
コンポーネントに関連付けられている状態が変更されていない場合でも、通知が届きます。

それを避けるために離れていますか?

react-reducerは、一部のアクションで一部のレデューサーサブツリーをスキップするのに役立つため、状態ツリーの更新は最小限に抑えられます。

何を指しているのかわからない。 私はそのようなプロジェクトを知りません。 https://github.com/omnidan/redux-ignoreのことですか?

しかし、状態の変化にサブスクライブされているすべてのコンポーネントはどうでしょうか。

これを処理するhttps://github.com/reactjs/react-reduxを使用し

元の議論が沈静化したので、私はこのスレッドを閉じます。

@gaearon

これを処理するhttps://github.com/reactjs/react-reduxを使用し

私はドキュメントで以下を読みました。

mapStateToProps(state、[ownProps]):stateProps :指定されている場合、コンポーネントはReduxストアの更新をサブスクライブします。 更新されるたびに、mapStateToPropsが呼び出されます。 その結果はプレーンオブジェクト*である必要があり、コンポーネントの小道具にマージされます

ここで何が起こっているのかを完全に理解したかったので、Reduxストアが更新されても、特定のコンポーネントの状態が変更されていない場合、ReduxはそのコンポーネントのforceUpdate()メソッドをトリガーしません。

答えがイエスなら、あなたは私の日を作りました:)

React ReduxはforceUpdate()をまったく使用しません。 それははるかに注意深いです:-)
はい、不要な更新が発生することはありません。

具体的には、React-Reduxのconnect()関数によって生成されたラッパーコンポーネントは、実際のコンポーネントを再レンダリングする必要がある回数を最小限に抑えるために、いくつかのチェックを実行します。 これには、 shouldComponentUpdateデフォルトの実装と、コンポーネントに入る小道具の浅い等価性チェックの実行が含まれます( mapStateToPropsから返されるものを含む)。 そうです、原則として、接続されたコンポーネントは、状態から抽出している値が変更された場合にのみ再レンダリングされます。

:+1:甘い。

このページは役に立ちましたか?
0 / 5 - 0 評価