question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Discussing the future of schedulers

See original GitHub issue

Schedulers exist so we can exercise more control over when subscription occurs and when values are observed. They also provide a mechanism we can hook to get more deterministic tests that run very fast.

A few issues with the current Scheduler set up

  1. It’s hard to build a test suite for people.
  • do we need a global default scheduler? Should we just pass one around?
  • if an operator defaults to a particular scheduler, do we patch it to make it use a test scheduler during test scenarios?
  1. It’s a large and complicated part of the library
  2. It’s a little-understood part of the library
  3. Scheduler arguments aren’t symmetric with proposed Observable APIs, like Observable.of
  4. Still doesn’t make it much easier to test things like animationFrame or the like.
  5. When a scheduler is needed, it must be passed around and provided to every Observable creation call and time-related operator.

Questions

  • In practice, is it better to have an Observable.of(1, 2, 3, async) or Observable.asyncOf(1, 2, 3)? Observable.of(1, 2, 3, asap) or Observable.microtaskOf(1, 2, 3) (name totally bike-sheddable)
  • Could we potentially just use setTimeout or Promise then, and patch them temporarily at test time? It seems like that might make it easier to build test suites. It might also reduce the size of the library.
  • How much do people really find the need to use Schedulers? How valuable are they if we found another way to deterministically test Observables?
  • Would scaling them back a great deal reduce the size of the library significantly?

Other things

Having schedulers might enable us to centralize error handling in the next version, which could help performance and reduce library size. This was one of the central changes in “T-Rex”.

NOTE: This is just a discussion to get us to question what we’ve been doing with schedulers, not a change suggestion per say

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:29 (22 by maintainers)

github_iconTop GitHub Comments

4reactions
trxcllntcommented, Oct 15, 2017

@benlesh I’m still in favor of an option to specify the scheduler at subscription time, which would compose all the way through the operator subscriptions and could be used in place of operator defaults, e.g. subscribe(observer, scheduler). Tests would then just need to pass the TestScheduler as the second argument when they subscribe.

3reactions
trxcllntcommented, Oct 16, 2017

@benlesh The overall issue we have with Schedulers right now in RxJS, IMO, is that we’ve over-engineered the solution a bit. Scheduling makes more sense in a multi-threaded environment. The only scheduling distinction I’ve seen make a lot of sense for us is breadth-first vs depth-first scheduling, but even that is fairly edge-casey, honestly.

Scheduling is about concurrency, not threading. Threads are a type of concurrency, but not the only kind. That said with SharedArrayBuffers and workers, JS is getting a type of threading whether we like it or not.

Well, anything with any sort of delay really just ends up using setTimeout

Do you mean JS in general, or in Rx? We explicitly use setInterval instead of setTimeout in the AsyncScheduler, because setTimeout can’t reliably execute intervals (esp. under load), nor does it reliably synchronize with items scheduled using setInterval, leading to heisenbugs.

I think that the animationFrame scheduler might be an exception there, but honestly, I’m still not sure animationFrame is best as a scheduler, when it could just be an observable.

Synchronizing events on the animationFrame is an absolute necessity for performance. It’s totally a scheduler thing. events.auditTime(0, Scheduler.animationFrame).subscribe(render) is one of the most common things in our front-end code.

If we stepped back to use wrapped, native scheduling APIs, we could reduce a lot of code, and simplify and even speed up our operators substantially.

First, we do use the native scheduling APIs. Schedulers aren’t meant to replace those APIs, they’re meant to abstract calling those APIs away from the specific Observable/operator implementations. By abstracting the logic of calling native scheduling APIs, we can then parameterize which APIs Observables and operators ultimately use. This is a critical component of what makes Rx a superset of pure FRP.

Second, the schedulers are very lean. The current design was meant to simplify/unify the scheduling interface behind a single schedule method that can schedule either one or infinite executions, with or without state, for fixed or changing periods. The API was explicitly designed so we could eliminate additional Subscription allocations across intervals by implementing a form of async tail-recursion, which improves scheduler performance and reduces GC churn:

// This only allocates a single Subscription for infinite execution
scheduler.schedule(function(i) {
  this.schedule(i+1, 100);
}, 0, 100);

Considering the apparent difficulty of implementing efficient/safe async scheduling, I’m extremely skeptical of the safety of hard-coding scheduling logic into the Observables and operators themselves. Seems like a heap 'o trouble.

@jhusain Why not split these operators in two? For example have Observable.of, and Observable.ofWithScheduler? This way developers who are not using schedulers don’t have to pay for them.

What do you mean? Unless something’s changed since I last looked, of doesn’t have a default scheduler.

Alternately if we can find a way to dramatically reduce the file size by simplifying the available schedulers, that would be nice as well.

I’ve mentioned before to @benlesh we absolutely can reduce the LOC in the Schedulers. Frankly the only reason they’re broken down into so many classes is because I didn’t want to confuse anybody in the last big scheduler PR. I’d be happy to submit a PR that reduces the LOC in schedulers by combining logic into a single parameterized Action class.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Future of scheduling - too good to be true? - Timezynk
Employee scheduling has changed a lot during the years, from pen and paper to AI-based technology. With digital transformation continuing to ...
Read more >
Ace the System Design Interview: Job Scheduling System
In this article, I want to share with you my design of large-scale job schedulers based on my own experience and discussions with...
Read more >
A Future is a Suspending Scheduler - Nikhil's blog
This scheduler (when combined with a suitable rebuilder) provides a minimal build system that supports dynamic dependencies.
Read more >
The future of work in manufacturing - Deloitte
In the construction site of 2025, many scheduling tasks are automated; the tracking of labor, equipment, and raw materials are digitalized; and performance...
Read more >
Examining the developments in scheduling algorithms research
Edge Computing is the most discussed topic concerning scheduling algorithms research in 2020 and 2021. •. Institutional collaborations have not ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found