在Node.JS中,有没有办法让Array.prototype.sort()屈服于其他进程?

在Node.JS中,有没有办法让Array.prototype.sort()屈服于其他进程?,node.js,Node.js,仅供参考:我已经在和网络工作者一起做这件事了,效果很好,但我只是在探索process.nextTick可以做什么和不能做什么 所以我有一个包含一百万个元素的数组,我正在Node.JS中进行排序。我希望节点在执行此操作时能够响应其他请求 有没有办法使Array.prototype.sort()不阻塞其他进程?由于这是一个核心函数,因此无法插入任何进程。nextTick() 我可以手动实现快速排序,但我看不出您是如何以延续传递方式高效地实现快速排序的,这似乎是process.nextTick()所必

仅供参考:我已经在和网络工作者一起做这件事了,效果很好,但我只是在探索process.nextTick可以做什么和不能做什么

所以我有一个包含一百万个元素的数组,我正在Node.JS中进行排序。我希望节点在执行此操作时能够响应其他请求

有没有办法使Array.prototype.sort()不阻塞其他进程?由于这是一个核心函数,因此无法插入任何进程。nextTick()


我可以手动实现快速排序,但我看不出您是如何以延续传递方式高效地实现快速排序的,这似乎是process.nextTick()所必需的。我可以修改for循环来实现这一点,但sort()似乎是不可能的。

好吧,我最初认为您可以使用它,但仔细检查后,它似乎不会按照您的需要运行。请参阅以了解类似的问题,尽管目前还没有公认的答案。

虽然不可能使
Array.prototype.sort
本身以某种方式异步运行,但异步排序绝对是可能的,如所示,以演示setImmediate(shim)相对于setTimeout的速度优势

不幸的是,源代码似乎没有任何许可证。演示的Github repo指定Jason Weber为作者。你可能想问他你是否想使用(部分)代码

我认为,如果使用setImmediate(从节点0.10开始提供),各个排序操作将与I/O回调有效地交织在一起。对于如此大量的工作,我不推荐process.nextTick(如果它能工作的话,因为有1000个maxtick深度限制)。看看有什么背景

使用setImmediate而不是普通的“同步”处理总体上肯定会比较慢,因此您可以选择在每个“勾号”上处理一批单独的排序操作来加快速度,而代价是节点在此期间没有响应。我认为只有通过实验才能找到速度和响应性wrt I/O之间的正确平衡

一个更简单的替代方法是更像web工作者:生成一个子进程并在那里进行排序。然后,您面临的最大问题是将排序后的数据传输回主进程(大概是为了生成某种输出)。好了,Node.js没有比这更好的了。缓冲排序后的数组后,可以将结果流式传输到子进程stdout,并在主进程中解析数据,或者更简单;使用


您可能没有备用的cpu核心,因此子进程会占用其他进程的cpu时间。为了避免排序进程损害其他进程,您可能需要为其分配低优先级。似乎不可能对节点本身执行此操作,但您可以尝试使用
nice
,如下所述:。我在这件事上没有经验。

我知道这是一个相当老的问题,但我遇到了类似的情况,仍然找不到简单的解决办法

我修改了一个exising quick sort并发布了一个包,在这里定期放弃对eventloop的执行:

如果您熟悉传统的快速排序,我唯一的修改就是对执行分区的初始函数进行修改。基本上,该函数仍然在原地修改数组,但现在返回一个承诺。如果它试图在一次迭代中处理过多的元素,它将停止eventloop中其他内容的执行。(我相信我指定的默认大小是10000)

注意:在此处使用setImmedate而不是process.nextTick或setTimeout很重要。nextTick实际上会将您的执行置于进程IO之前,并且您在响应与IO相关的其他请求时仍然会遇到问题。setTimeout太慢了(我相信其中一个答案链接了一个演示)

注2:如果像mergesort这样的东西更符合您的风格,那么您可以在sort的“merge”函数中执行相同的逻辑

const immediate = require('util').promisify(setImmediate);

async function quickSort(items, compare, left, right, size) {
  let index;
  if (items.length > 1) {
    index = partition(items, compare, left, right);
    if (Math.abs(left - right) > size) {
      await immediate();
    }
    if (left < index - 1) {
      await quickSort(items, compare, left, index - 1, size);
    }
    if (index < right) {
      await quickSort(items, compare, index, right, size);
    }
  }
  return items;
}
const immediate=require('util').promisify(setImmediate);
异步函数快速排序(项目、比较、左、右、大小){
let指数;
如果(items.length>1){
索引=分区(项目、比较、左、右);
if(数学abs(左-右)>尺寸){
等待立即的;
}
如果(左<索引-1){
等待快速排序(项目、比较、左侧、索引-1、大小);
}
如果(索引<右){
等待快速排序(项目、比较、索引、右键、大小);
}
}
退货项目;
}

完整的代码在这里:

Yeah-async和类似的库用于将已经异步的函数连接在一起,而不会从回调地狱中发疯。它们不会神奇地使函数异步或无阻塞。这就是为什么我们有
process.nextTick()
.Links rot,在提供的答案中包含代码。@Trenton\M所以要链接github,或者实际发布整个源代码或相关源代码?在这种情况下,我会包含示例并提供链接。或者,我个人会将此作为对问题的评论。不过,在这篇文章中我看到了很多链接,所以我耸耸肩。试着跟着做。@Trenton_M这看起来更好吗?答案的质量更好。