Monifu でのスケジューリングに関する注意事項 - Monifu は非同期パイプラインを折りたたもうとするため、下流のオブザーバーが本質的に同期している場合、Monifu はタスクをスケジューラーに送信することを回避します。Monifu はバックプレッシャーも行うため、Scheduler に送信されるタスクの数を制御するため、ブラウザーのキューが爆発するような状況に陥ることはありません。
たとえば、このようなものObservable.range(0,1000).foldLeft(0)(_+_).map(_ + 10).filter(_ % 2 == 0)
は、最初のループを開始するためにスケジューラで単一のタスクのみを送信しています。それ以外の場合、オブザーバーも同期的であり、そのキュー内の他のタスクを送信しない場合、パイプライン全体が完全に同期的です。そして、そのソースがどれくらい大きくなるかわからないため、キューの最初のタスクを送信します。通常、データソースへのサブスクライブは、ブロックしたくない UI の更新に関連して行われます。
3 つの大きな例外があります。
- バックプレッシャーをサポートしていないデータ ソースを使用している (Web ソケット接続など)
- 受信(つまり、オブザーバー)に実際の非同期境界があります。これは、たとえば外部サービスと通信するときに発生する可能性があり、それがいつ完了するかわからない実際の未来です
可能ないくつかの解決策...
- サーバー通信がバックプレッシャをサポートしていない場合、最も簡単な方法は、バックプレッシャをサポートするようにサーバーを変更することです。また、通常の HTTP リクエストはバックプレッシャが自然に行われます (つまり、次のように簡単です)。
Observable.interval(3.seconds).flatMap(_ => httpRequest("..."))
- それがオプションでない場合、Monifu にはバッファリング戦略があります...したがって、無制限のキューを使用できますが、バッファオーバーフローをトリガーして接続を閉じるキュー、またはバックプレッシャーを実行しようとするバッファリングも使用できます。バッファがいっぱいになると新しいイベントのドロップを開始し、古いイベントをドロップするための別のバッファリング戦略に取り組んでいます-キューの切断を回避する目的で
- 無制限にできるソースのソースで「マージ」を使用している場合は、それを行わないでください;-)
- 外部サービスへのリクエストを行っている場合は、それらを最適化してみてください。たとえば、イベントを Web サービスに送信して履歴を追跡したい場合は、データをグループ化し、リクエストをバッチ処理することができます。
ところで、ブラウザ側とタスクのスケジューリングの問題に関して、私が心配していることの 1 つは、Monifu が作業を効率的に中断しないことです。言い換えれば、おそらく長い同期ループを小さなループに分割する必要があります。なぜなら、一部のループが UI の更新をブロックしているため、パフォーマンスの問題に苦しむよりも悪いのは、UI に表示されるレイテンシの問題だからです。大きなタスクではなく、複数の小さなタスクをスケジューラに送信したいと考えています。ブラウザーでは、基本的に協調マルチタスクがあり、UI の更新を含め、すべてが同じスレッドで行われます。つまり、このスレッドを長時間ブロックする作業を行うのは非常に悪い考えです。
そうは言っても、私は現在、Javascript ランタイムを最適化し、より注意を払っているところです。setTimeout
よりも標準的であるため、使用されていますが、これらsetImmediate
の側面についていくつかの作業を行います。
ただし、パフォーマンスが悪い具体的なサンプルがある場合は、ほとんどの問題を修正できるため、それらを伝えてください。
乾杯、