NodeJS,承诺和表现

时间:2016-06-23 07:36:48

标签: node.js performance memory nested-loops es6-promise

我的问题是我的NodeJS应用程序中的性能......

如果我的程序运行12次迭代,每次1.250.000 = 15.000.000次迭代 - 它需要在亚马逊的专用服务器处理以下时间:

  

r3.large:2个vCPU,6.5个ECU,15个GB内存 - > 123分钟

     

4.8xlarge:36 vCPU,132 ECU,60 GB内存 - > 102分钟

我在下面的代码中有一些代码similair ...

start();

start(){

  for(var i=0; i<12; i++){

      function2();    // Iterates over a collection - which contains data split up in intervals - by date intervals. This function is actually also recursive - due to the fact - that is run through the data many time (MAX 50-100 times) - due to different intervals sizes...
    }
}

function2(){

  return new Promise{

    for(var i=0; i<1.250.000; i++){       
         return new Promise{      
            function3();      // This function simple iterate through all possible combinations - and call function3 - with all given values/combinations
         }
      }   
   } 
}


function3(){
   return new Promise{ // This function simple make some calculations based on the given values/combination - and then return the result to function2 - which in the end - decides which result/combination was the best...
}}

这相当于0.411毫秒/ 441微秒的迭代次数!

当我查看任务栏中的性能和内存使用情况时... CPU没有以100%的速度运行 - 但更像是50%...整个时间? 内存使用率开始非常低 - 但KEEPS以GB为单位 - 每分钟一直持续到进程完成 - 但是当我按下Windows CMD中的CTRL + C时,(分配的)内存首先被释放...所以它就像NodeJS垃圾回收一样不是最佳工作 - 或者可能是它的代码设计简单......

当我执行应用程序时,我使用内存选项如:

  

node --max-old-space-size =“50000”server.js

请告诉我你能做的每一件事 - 让我的节目更快!

谢谢大家 - 非常感谢!

1 个答案:

答案 0 :(得分:7)

垃圾收集器不是最佳,但它根本不能正常工作 - 你没有给它任何机会。

开发在节点中进行tco module优化的tail call时,我发现了一件奇怪的事情。它似乎泄漏了记忆,我不知道为什么。事实证明,这是因为console.log()很少 在我用于测试的各个地方调用以查看发生了什么,因为看到数百万级深度递归调用的结果需要花费一些时间,因此我希望在执行此操作时看到某些内容。

你的例子非常相似。

请记住,Node是单线程的。当您的计算运行时,没有其他任何东西可以 - 包括GC。您的代码完全同步并阻塞 - 即使它以阻塞方式生成数百万个承诺。它是阻塞的,因为它永远不会到达事件循环。

考虑这个例子:

var a = 0, b = 10000000;

function numbers() {
  while (a < b) {
    console.log("Number " + a++);
  }
}

numbers();

这很简单 - 你想打印1000万个数字。但是当你运行它时它表现得非常奇怪 - 例如它打印数字到某个点,然后它会停止几秒钟,然后它继续运行或者如果你使用交换它可能会开始捣乱,或者可能会给你这个错误我看到第8486号后才刚刚开始:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
Aborted

这里发生的是主线程在同步循环中被阻塞,它继续创建对象,但GC没有机会释放它们。

对于如此长时间运行的任务,您需要划分工作并偶尔进入事件循环。

以下是解决此问题的方法:

var a = 0, b = 10000000;

function numbers() {
  var i = 0;
  while (a < b && i++ < 100) {
    console.log("Number " + a++);
  }
  if (a < b) setImmediate(numbers);
}

numbers();

它也是这样 - 它将数字从a打印到b,但是以100的串数打印,然后它会自行安排在事件循环结束时继续。

$(which time) -v node numbers1.js 2>&1 | egrep 'Maximum resident|FATAL'

的输出
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
    Maximum resident set size (kbytes): 1495968

它使用了1.5GB内存并崩溃了。

$(which time) -v node numbers2.js 2>&1 | egrep 'Maximum resident|FATAL'

的输出
    Maximum resident set size (kbytes): 56404

它使用了56MB内存并完成了。

另见答案: