2

I am building a page where users can generate custom timers. These timers are run on a heroku nodejs backend via setTimeout. I am, however, a little worried about having possibly thousands of long time setTimeouts running concurrently.

I found this SO question, which states that javascript timers are run on a seperate thread in the browser. Is the same the case in nodejs? If so, what is the consequence of having thousands of timers on this thread?

edit: Some more info about what I am trying to do. I am building a synchronizing page, which can be put on a screen, where then users can access the page in the browser and change the content on their instance. This will then be reflected in all open instances of the page. Users should also be able to set timers, which should push new content at timer end. This is what I am considering using server side setTimeouts to do. I know I should probably use one of the heroku scheduler addons, but I would like to keep costs down (this kind of page is not exactly a moneymaker). Lastly, users should be able to generate their own instance of this page, with a new url and such. This is where the scalability question comes into play. If 100 instances of the page exists, and each instance has 10 timers set, that is 1000 timers on the backend.

Community
  • 1
  • 1
MyrionSC2
  • 1,248
  • 1
  • 14
  • 24
  • 3
    What exactly are you trying to do? "thousands of timers" doesn't sound like a proper solution for anything. – robertklep Jul 19 '15 at 11:24
  • It doesn't sound like a wise design decision, even if it will be "safe". If you'd explain your use case a little further I'm sure you'll be able to get some interesting responses (like, for example, not use `setTimeout` :-) – Amit Jul 19 '15 at 11:26
  • Why not just try it and see if it works for you or not? – mscdex Jul 19 '15 at 11:33
  • I have updated my question with more info. @mscdex I have a mind to :) But I don't want to waste too much time if setTimeout scales terribly. I have been unable to find much concrete information about how setTimeout works exactly, when it is counting down. When it activates there is a plethora of information about what happens (the js execution stack), but i am not really interested in that. I am more interested in what happens before it activates. – MyrionSC2 Jul 19 '15 at 11:40
  • As I commented above, that doesn't sound like a good design. It is highly unlikely your users will care (or even notice) how accurate the timers are. Use a single INTERVAL (say 1 sec between events --> `setInterval(..., 1000)`) and in that event process a list of times (not timers, just time values) and do what is needed for each one – Amit Jul 19 '15 at 11:41
  • 2
    Timers in NodeJS work via libuv timers and are implemented as a linked list. They're relatively fast and there is nothing to worry about if it's really just tens of thousands most likely. – Benjamin Gruenbaum Jul 19 '15 at 11:42
  • Also, you can use a single timer and check what timers have "expired" and fire the callbacks for them, not sure if it's more efficient though. – Benjamin Gruenbaum Jul 19 '15 at 11:42
  • @BenjaminGruenbaum - your comment about libuv's implementation is very interesting and informative. It perfectly answers the question as well. Why not post it as an answer? – Amit Jul 19 '15 at 11:44
  • FWIW node.js/io.js groups together timeouts with the same values and only uses a single timer for that group. – mscdex Jul 19 '15 at 11:44
  • @mscdex - how is "same values" defined? equality can be tricky here – Amit Jul 19 '15 at 11:45
  • Amit - because I'm at work and don't have time to elaborate and it looks like @mscdex is here and he's an io contributor so he probably knows this too and will post an answer. – Benjamin Gruenbaum Jul 19 '15 at 11:45
  • @BenjaminGruenbaum That's good to hear :) I'll read up on libuv now. As for your (and Amit's) second suggestion, I would have to check, let's say, a thousand timers utc time against the current utc time every second. It doesn't sound very efficient, but then again, I don't pay for the power :P I might as well put herokus servers to work. If setTimeouts doesn't work out, I will consider your solution. – MyrionSC2 Jul 19 '15 at 11:49
  • @MyrionSC2 - The single timer solution doesn't require to check every "timer" on every trigger. It only requires to have the timers in a sorted list. – Amit Jul 19 '15 at 11:52
  • @MyrionSC2 hint: keep the list sorted or use a heap – Benjamin Gruenbaum Jul 19 '15 at 11:54
  • @Amit&@BenjaminGruenbaum - Haha, didn't think of that. Feeling a little outclassed here ^^ – MyrionSC2 Jul 19 '15 at 11:56
  • @Amit The source code for timers.js is pretty easy to follow, but basically what happens is that all calls to both `setTimeout()` and `setInterval()` with the same expiration/interval are grouped together and use the same backing timer. These `setTimeout()`/`setInterval()` requests are appended to a list tied to that timer in the order they're added so that every time the timer fires, it iterates the list (executing callbacks) until it reaches a timeout that hasn't expired yet. At that point it waits the delta between the current time and the next timeout in that group. I hope that made sense. – mscdex Jul 19 '15 at 12:07
  • @mscdex - It made sense to me :) It is nice finally knowing it, it's something I've been curious about for some time. – MyrionSC2 Jul 19 '15 at 12:12

1 Answers1

3

Based on mscdex's explanation in the comments:

The source code for timers.js is pretty easy to follow, but basically what happens is that all calls to both setTimeout() and setInterval() with the same expiration/interval are grouped together and use the same backing timer. These setTimeout()/setInterval() requests are appended to a list tied to that timer in the order they're added so that every time the timer fires, it iterates the list (executing callbacks) until it reaches a timeout that hasn't expired yet. At that point it waits the delta between the current time and the next timeout in that group. I hope that made sense.

I have come to the conclusion, that having many setTimeouts are not detrimental to performance, as they are all really one timer. Just answering myself since no one else did.

MyrionSC2
  • 1,248
  • 1
  • 14
  • 24