1

Is it possible to define a boundary that shouldn't be crossed for the application to scale well regarding task scheduling (over)use?

Questions :

  1. Is there a certain cost of doing setTimeout? Let say 0.1ms or CPU time? There is certainly order of magnitude lower cost than spawning a thread in different environments. But is there any?
  2. Is it better to avoid using setTimout for micro tasks that take like 1-2 ms ?
  3. Is there something that doesn't like scheduling? For instance I noticed of some sort of IndexedDb starvation for write locks when scheduling Store retrieval and other things
  4. Can DOM operations be scheduled safely ?

I'm asking because I started using Scala.js and an Rx implementation Monifu that is using scheduling at massive scale. Sometimes one line of code submits like 5 tasks to an event loop's queue so basically I'm asking myself, is there anything like task queue overflow that would slow the performance down? I'm asking this question especially when running test suites where hundreds of tasks might be enqueued per second.

Which leads to another question, is it possible to list cases when one should use RunNow/Trampoline scheduler and when Queue/Async scheduler in regards to Rx? I'm wondering about this every time I write stuff like obs.buffer(3).last.flatMap{..} which itself schedules multiple tasks

4

1 回答 1

1

关于 Monifu 中调度的一些注意事项 - Monifu 试图折叠异步管道,因此如果下游观察者本质上是同步的,那么 Monifu 将避免将任务发送到调度程序。Monifu 也做背压,所以它控制有多少任务提交到调度程序,因此你不会最终出现浏览器队列爆炸的情况。

例如,这样的事情......Observable.range(0,1000).foldLeft(0)(_+_).map(_ + 10).filter(_ % 2 == 0)只是在调度程序中发送一个任务来启动该初始循环,否则如果观察者也是同步的,则整个管道是完全同步的,并且不应在该队列中发送任何其他任务。它发送队列中的第一个任务,因为它不知道该源将有多大,并且通常订阅数据源与您不想阻止的某些 UI 更新有关。

有 3 个大的例外:

  1. 您正在使用不支持背压的数据源(如网络套接字连接)
  2. 您在接收(即观察者)中有一个真正的异步边界,例如在与外部服务通信时可能发生这种情况,这是一个真正的未来,您不知道它何时会完成

一些解决方案可能...

  1. 如果服务器通信不支持背压,在这种情况下,最简单的做法是修改服务器以支持它 - 此外,正常的 HTTP 请求自然是背压的(即它就像Observable.interval(3.seconds).flatMap(_ => httpRequest("..."))
  2. 如果这不是一个选项,Monifu 有缓冲策略......所以你可以有一个无界队列,但你也可以有一个触发缓冲区溢出并关闭连接的队列,或者尝试做背压的缓冲,你也可以当缓冲区已满时开始丢弃新事件,我正在研究另一种用于丢弃旧事件的缓冲策略 - 目的是避免队列溢出
  3. 如果您在可以无限的来源上使用“合并”,那么不要这样做;-)
  4. 如果您正在向外部服务发出请求,请尝试优化它们 - 例如,如果您想通过将事件发送到 Web 服务来跟踪事件的历史记录,您可以对数据进行分组并执行批处理请求等

顺便说一句 - 关于浏览器端和任务调度的问题,我担心的一件事是 Monifu 没有足够有效地中断工作。换句话说,它可能应该将较长的同步循环分解成较小的循环,因为比遭受性能问题更糟糕的是在 UI 中可见的延迟问题,因为某些循环会阻止您的 UI 更新。我宁愿将多个较小的任务提交给调度程序,而不是一个更大的任务。在浏览器中,您基本上拥有协作式多任务处理,所有事情都在同一个线程上完成,包括 UI 更新,这意味着让该线程阻塞太久的工作是一个非常糟糕的主意。

也就是说,我现在正在优化并更加关注 Javascript 运行时。setTimeout使用它是因为它比 更标准setImmediate,但是我会在这些方面做一些工作。

但是,如果您有性能不佳的具体示例,请进行交流,因为大多数问题都可以解决。

干杯,

于 2015-03-03T17:27:17.230 回答