Redux: なぜカント状態が変化するのか....

作成日 2015年09月20日  ·  13コメント  ·  ソース: reduxjs/redux

こんにちは、

私は不変について、そしてどのようにあなたがあなたの状態を変えてはならないかについて興味を持って読みました。 それがなぜであるかはある程度理解していますが、私の「新しいオブジェクトの作成に費やされる時間についての懸念」の側面は、JSでこれがどれほど速いか遅いかを理解していないか、何か他のものが欠けています。

通常、新しいオブジェクトを作成し、古いオブジェクトを新しいオブジェクトに複製し、新しい状態の追加(または減算)を行うと、既存の状態を変更するよりも時間がかかるように思えます。 だから私は不変のものがなぜそれほど重要であるのかを理解しようとしています、そしてそれは私がちょうど見ないチェーンの他の何かに影響を与えますか?

さらに..Reductが提供するものの多くをreact-coreに追加でき、おそらくそのDOM差分エンジンを利用することさえできると思います...おそらく状態を変更する必要があるかどうかを判断するのに役立ちます。 状態を変更するプロセスが、状態を新しい状態と比較して、変更する必要がある実際の状態オブジェクトの部分のみを変更(変更)するよりも速いか遅いかがわかりません。

私はこれらすべてに比較的慣れていないので、状態を変更しないという概念の周りに何かが欠けている場合は許してください。 コンポーネントは不変のデータのみをレンダリングする必要があるという考えが大好きです...しかし、繰り返しになりますが、コンポーネントは不変であるかどうかを気にせず、知りません。どこかから渡されるデータだけなので、私は苦労しています。全体の不変状態と可変状態のビット。

question

最も参考になるコメント

明確にするために、状態はすべてのアクションで深くクローン化されるわけではありません。 変更された部分のみが複製されます(ここでも、深くではなく、何が変更されたかによって異なります)。 たとえば、TodoMVCアプリでTodoを編集すると、そのTodoオブジェクトのみが複製されます。 残りのtodoオブジェクトは同じです。 もちろん、新しいオブジェクトを指すルートの新しいToDoリスト配列が作成されますが、オブジェクトが変更されていない場合、オブジェクト自体は複製されません。 したがって、見た目ほど高価ではありません。 さらに、コストが高くなると(たとえば、配列の高速変更)、構造共有のおかげでコピーが非常に高速なImmutable.jsのようなライブラリの使用を開始できます。 Immutable.jsを使用すると、メモリの大きなチャンクが再利用されるため、大きな配列をコピーするのにそれほど費用はかかりません。 最後に、Immutable.jsの有無にかかわらず、オブジェクトが変更されていないために_正確に_何が変更されたかがわかっているため、不変性はアプリを効率的に再レン​​ダリングするのに役立ちます。

全てのコメント13件

予測可能性と信頼性がすべてです。

reduxのレデューサーは純粋関数です。つまり、副作用はありません。 これらの関数の外部状態を調べ始めるとすぐに、それらは純粋ではなくなります。 そして、それらが純粋でない場合、それらは信頼できない可能性があります。 そして、それはバグを引き起こし、その多くは追跡するのが_非常に_難しい場合があります。

純粋関数を作成することで、コードで発生するエラーが少なくなり、生産性が向上することがわかりました。 そして、ホットモジュールのリロード(純粋関数を使用して有効化)は、その生産性に加えてターボチャージャーです。

そして、あなたは非常に便利なタイムトラベルのような無料の機能を受け取ります。

#328の複製として終了します。

明確にするために、状態はすべてのアクションで深くクローン化されるわけではありません。 変更された部分のみが複製されます(ここでも、深くではなく、何が変更されたかによって異なります)。 たとえば、TodoMVCアプリでTodoを編集すると、そのTodoオブジェクトのみが複製されます。 残りのtodoオブジェクトは同じです。 もちろん、新しいオブジェクトを指すルートの新しいToDoリスト配列が作成されますが、オブジェクトが変更されていない場合、オブジェクト自体は複製されません。 したがって、見た目ほど高価ではありません。 さらに、コストが高くなると(たとえば、配列の高速変更)、構造共有のおかげでコピーが非常に高速なImmutable.jsのようなライブラリの使用を開始できます。 Immutable.jsを使用すると、メモリの大きなチャンクが再利用されるため、大きな配列をコピーするのにそれほど費用はかかりません。 最後に、Immutable.jsの有無にかかわらず、オブジェクトが変更されていないために_正確に_何が変更されたかがわかっているため、不変性はアプリを効率的に再レン​​ダリングするのに役立ちます。

ああ....最後のビットが今意味をなすのを見てください...これによって、どの状態が変更されたかだけによるコンポーネントのレンダリング変更のために、結果として反応差分/再描画エンジンが高速になると言っていると思いますか? shouldComponentUpdateに似ていると思います

これにより、どの状態が変化したかによってコンポーネントのレンダリングが変化するため、結果として、react diff / redrawエンジンが高速になるとおっしゃっていると思いますか? shouldComponentUpdateに似ていると思います

正確には、 react-reduxは、不変性の保証のおかげで、内部で積極的なshouldComponentUpdateを使用します。

@gaearonこれを少し

さらに、コストが高くなると(たとえば、配列の高速変更)、構造共有のおかげでコピーが非常に高速なImmutable.jsのようなライブラリの使用を開始できます。

8000ポジションまでのアレイへの更新を処理するためにreduxを使用することを検討しており、スループットは100ミリ秒あたり10〜100回の変更の範囲になると予想しています。 reduxを使用してそのように状態を管理しようと負け戦を戦っていますか?
DOMではなくキャンバスを介して状態を表現することを計画していますが、あなたの経験では、更新の頻度が問題を引き起こすかどうかを理解したいと思います。

@dougajmcdonald :私の最初の質問は、その作業のいずれかを何らかの方法で

それ以外にも、Redux関連のパフォーマンスに関する次のリソースを確認することをお勧めします。

また、 Reactifluxチャットチャネルでこれについてさらにます

@markerikson残念ながらそうです、ゲームのコンセプトには、比較的大きなデータ構造への多くの高速更新が含まれます。
元のコメントでは完全に明確ではなかったことに気づきました。10〜100の変更を言った場合、これらすべてが再描画をトリガーするわけではありません。 10〜100の変化は、100ミリ秒ごとに1回の再描画で表される状態変化です。
したがって、私の質問は、更新を100ミリ秒あたり10〜100の状態変更にバッチ処理する場合、redux内の状態管理は、100ミリ秒のウィンドウ内で適切に完了する方法でこれらを効果的に処理できるかどうかです。物事が遅れ始めることなく再描画を許可します。
状態の更新には、基本的にサイズ8000の配列の3〜4個のプロパティの変更が含まれるため、1ミリ秒あたり1〜10回(物事を不変に保ちたいと仮定して)新しい配列を作成し、次のいずれかに変更を加えることについて話します。配列インデックス内のオブジェクト。 オブジェクトは非常に小さいです(3〜4個のプロパティ、2つの数字、および2つの小さな文字列)

これが、Danが提案したように、配列をできるだけ多く再利用できるかのように不変を使用することの利点について疑問に思った理由です。これにより、パフォーマンスが向上する可能性があります。

@dougajmcdonald

Immutable.jsは、魔法のパフォーマンスを向上させる銀の弾丸ではありません。 いくつかのことを速くし、他のことを遅くすることができます。 Immutable.jsに関連するパフォーマンスの考慮事項に関する複数の記事があります。

正直なところ、ユースケースを考えると、理論的には、必要に応じて直接突然変異を回避することができます。 私の投稿IdiomaticRedux、パート1-実装とインテントによると、Reduxコア自体は実際にはミュー

私の個人的なアドバイスは、簡単に始めることです。 プレーンなJSオブジェクトと配列を使用するだけです。 「手動で」、または利用可能多くの不変に更新します。 それがあなたにとってどれほどうまく機能するかを見てください。

次に、そこから、バッチ処理、ディスパッチの削減、ロジックの更新などの点で追加の最適化作業を行うことができます。

@markerikson微妙なジャイブが鼻にかかった! :pええ、現時点でのレデューサー側は基本的にかなり大きな配列の作成と破棄ですが、実際の問題は、最終目標が達成されるときに、reactコンポーネントのライフサイクルビットとボブである可能性が高いと思います理想的には60ishFPSでレンダリングするcanvas要素。
不変のポイントと直接突然変異のポイントに感謝します。少し読んで、これらも検討します。
現時点での私の思考プロセスは、redux状態をキャンバスから切断し、より多くの可動部分を使用してpub / subを介してメッセージを渡すことです(これはすでに接続されています)。

私はから変更することを考えています:
pubsub> dispatch()>レデューサー> redux状態> reactコンポーネントのもの>キャンバスレンダリング。

に:
pubsub>ローカルコンポーネントの状態>キャンバスレンダリング

おそらくアプリのキャンバス部分ではなく、UIの残りの部分には引き続きreduxを使用します。

あなたの質問は完全に有効です。 実際、vuexと呼ばれるreduxのvuejs実装は、ミューテーションの概念の下で機能します。 したがって、「リデューサー」は実際には突然変異と呼ばれ、一元化された場所で状態を変更する限り、すべてが正常であるはずです。 これは、vueがオブザーバーやその他のものをアプリの状態に追加するために発生します。そのため、vueの場合、オブジェクトを置き換えるよりも変更する方が理にかなっています。 Reduxは不変であり、最終的には両方のアプローチのパフォーマンスがVS vue仮想DOM更新に反応しますが、すべての場合で一方が他方より優れているとは言えない点でほとんど同じです。

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