本文介绍了在设置大量计时器或使用计划的任务队列之间寻找解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一种服务(游戏),其中一组用户将位于一个房间中,该房间将在一定的时间段内(例如30秒)让每个用户进行选择.如果用户在此期间内未做出选择,则该服务将自动为该用户生成选择.如果在持续时间完成之前做出选择,则下一个用户启动,计时器应重置.

I'm building a service (a game) in which a group of users will be in a room where it will go through each user to make a choice within a certain duration (eg 30s). If the user does not make a choice within that duration, the service will auto generate a choice for that user. If a choice is made before the duration is done, then the next user is up and the timer should reset.

一次可能有成百上千个这样的房间/游戏.

There could be hundreds or even thousands of these rooms/games going on at a time.

我想知道如何实现它,并且愿意使用Javascript或Python解决方案.

I'm wondering how to implement this and I'm open to using Javascript or Python solutions.

对于Python,我当时想从线程库中生成尽可能多的计时器,但是不确定性能的影响.所有需要做的就是自动生成一个完全不占用资源的选择,然后使用SQLAlchemy来更新postgres.

For Python, I was thinking of spawning as many timers from the threading library as necessary, but unsure of the performance implications. All that needs to be done is auto generate a choice which isn't resource intensive at all, and updating postgres with it with SQLAlchemy.

我也可以使用celery,并使用相同的方法为我的消息代理提供延迟任务.

I could also use celery and feed my message broker with delayed tasks with the same method.

对于Javascript,类似于python的第一个解决方案,我可以根据需要生成尽可能多的setTimeouts,但是问题是所有超时都在主线程上起作用,但是就像我说的那样,任务并不占用资源,我只需要精确到秒.

For Javascript, similar to the python's first solution, i could spawn as many setTimeouts as necessary, but the problem is that all timeouts work on the main thread, but like i said, the tasks are not resource intensive and I only need accuracy to the second.

这些是到目前为止我所介绍的唯一解决方案,我想知道什么是最好的,并且对其他解决方案也开放.

These are the only solutions I've covered so far, I"m wondering what would be the best and open to other solutions as well.

推荐答案

Node.js计时器非常有效地实现.它们的实现(在有关它们如何工作的详细文章中进行了介绍)可以轻松处理非常多的计时器.

Node.js timers are very efficiently implemented. Their implementation (described in a detailed article about how they work) can easily handle very large numbers of timers.

它们被保存在一个已排序的双向链表中,只有下一个要触发的计时器才具有与之关联的实际libuv系统计时器.当该计时器启动或被取消时,列表中的下一个计时器将变为附加到实际libuv系统计时器的计时器.设置新的计时器后,它将被插入已排序的列表中,除非它成为要触发的下一个计时器,否则它将仅位于列表中,等待下一个开始.您可以非常高效地拥有成千上万个此类邮件.

They are kept in a doubly linked list that is sorted and only the next timer to fire has an actual libuv system timer associated with it. When that timer fires or is canceled, the next one in the list becomes the one attached to an actual libuv system timer. When a new timer is set, it is just inserted into the sorted list and, unless it becomes the next one to fire, it just sits in the list waiting its turn to be next. You can have thousands of these very efficiently.

以下是有关这些计时器如何工作的一些资源:

Here are a couple resources on how these timers work:

在发生性能问题之前有多少个并发setTimeout?

nodejs如何在内部管理计时器

第一个参考文献包含来自实际nodejs代码的大量注释,这些注释描述了计时器链表系统的工作方式以及针对其进行了优化的内容.

The first reference contains a bunch of comments from the actual nodejs code that describes how the timer linked list system works and what it's optimized for.

第二篇文章为您提供了有关其组织方式的更高层​​次的描述.

The second article gives you a little higher level description of how its organized.

还有其他效率,因此当一个计时器到达列表的开头并触发时,然后在调用该回调之后,node.js会检查列表的开头是否有其他现在也准备触发的计时器.这将清除所有具有与第一个相同的目标时间"的其他计时器,以及在这些其他各种回调运行时到期的所有其他计时器.

There are other efficiencies so that when one timer gets to the start of the list and it fires, then after calling that callback, node.js checks the front of the list for any other timers that are now ready to fire also. This will sweep up any other timers with the same "target time" as the first one and also any others that have come due while these various other callbacks were running.

当您有数千个计时器时,如果其中有很多计时器,则将新计时器插入到已排序的链表中会花费稍长的时间,但是一旦插入,则根本没有关系,因为只有一个计时器曾经看着下一个要开火的人.因此,坐在那里甚至有成千上万个计时器处于等待状态的过程仅仅是一个系统计时器(代表要触发的下一个计时器事件)和一堆数据.将来其他计时器的所有数据都不会花您任何钱.

When you have thousands, it will take slightly longer to insert a new timer into the sorted linked list if there are lots of timers in there, but once it is inserted, it hardly matters at all how many there are because it's only ever looking at the next one to fire. So, the process of sitting there with even tens of thousands of timers pending is just one system timer (representing the next timer event to fire) and a bunch of data. All that data for the other future timers isn't costing you anything just sitting there.

在我看来,nodejs可以很好地处理您的setTimeout()个调用.如果您在node.js中遇到问题,那不是由于计时器的数量而引起的,但是如果您要处理的工作量超过一个内核所能处理的数量,则必须确保为该问题使用了足够的CPU.您可以通过nodejs集群或使用工作线程或其他nodejs进程来帮助进行处理的工作队列来扩展核心用途. node.js本身对任何与I/O相关的事情都非常有效,因此只要您不进行大量的CPU密集型计算,单个node.js线程就可以处理很多事件处理.

It seems to me that nodejs could handle your quantity of setTimeout() calls just fine. If you had an issue in node.js, it wouldn't be because of the number of timers, but you would have to be certain that you apply enough CPU to the problem if you have more work to process than one core can handle. You could expand core usage with nodejs clustering or with a work queue that uses Worker Threads or other nodejs processes to help with the processing. node.js is, by itself, very efficient with anything I/O related so as long as you're not doing major CPU-intensive computation, a single node.js thread can handle a lot of event processing.

请记住,Javascript计时器不保证准确性.如果您使CPU陷入困境,则某些计时器的启动时间会比计划的晚,因为它们不是抢占式的.但是,如果您的任务不占用大量CPU,那么您就可以了.

Keep in mind that Javascript timers make no accuracy guarantees. If you bog down the CPU, some timers will fire later than scheduled because they aren't pre-emptive. But, if your tasks are not CPU-intensive, then you may be just fine.

这篇关于在设置大量计时器或使用计划的任务队列之间寻找解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-07 03:59