2016-06-23 15 views
0

私の質問は、私のNodeJSアプリでのパフォーマンスについてです...NodeJS、約束や性能

私のプログラムは、すべて一緒に、各= 15.000.000回の反復1.250.000の12反復を実行した場合 - それはアマゾンで、専用のサーバーを取りますプロセスに時間を次

r3.large:2のvCPU、6.5 ECU、15ギガバイトのメモリ - > 123分

4.8xlarge:36のvCPU、132 ECU、60ギガバイトのメモリ - > 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を押すと(割り当てられた)メモリが最初に解放されます。コレクションに最適な動作しませしません - または再びコードのシンプルなデザインかもしれ...

私はのようなメモリOPTを使用するアプリケーションを実行します。

ノード--max-古いです-space-size = "50000" server.js

私ができることすべてを教えてください - 私のプログラムをもっと速くしてください!

ありがとうございました!

+0

はまた、これらの回答を参照してください。ループをスピードアップする方法に焦点を当てるのではなく、アプリケーションをかなり再構成する必要があるように聞こえ始めます。あなたのアプリが何をしているのかについて、より多くの情報を提供できますか?なぜあなたはその多くの約束を必要としていますか? 'function3'は何をするのですか? – robertklep

+0

まず最初に、Nodeに新しい...だから、設計上の誤りは非常に可能かもしれません!要するに...プログラムはDBにアクセスしたり、ディスクに書き込んだり、多くの繰り返しを要求したりすることはありません...単純な配列やオブジェクトで単純に動作します。多くのデータで...これはDBからフェッチされています - これ前のステップで...なぜ私が約束を使用しているかは、ノードiが設計上非同期であるためです - そして、それ?私は、.Net/C#のような同期コードを使って作業していました... – PabloDK

+0

約束の中の折り返し計算は、必ずしもそれがずっと良くなるとは限りません。あなたがgoogle for _ "node heavy computation" _を使っていれば、単一のNodeプロセスより多くのCPUリソースを利用して、異なる子プロセスで計算を分割する方法についての良い指針を見つけることができます。また、あなたに役立つ[様々なモジュール](https://npms.io/search?term=computation+parallel)もあります。 – robertklep

答えて

5

これは、ガベージコレクタが最適が、それはすべてのでを動作しないこと動作しないということではない - あなたはそれに任意のチャンスを与えることはありませんが。

tco moduletail callであるノードiを最適化すると、奇妙なことに気付きました。記憶が漏れているように見えましたが、私は理由を知らなかった。私が何かをしている間に何かを見たいと思っていたので、再帰的な呼び出しの結果を見るためにテストに使用された様々な場所では、数多くの電話がconsole.log()であったことが判明しました。

あなたの例は、それにかなり似ています。

ノードはシングルスレッドであることに注意してください。計算が実行されると、GCを含めて何も実行できません。ブロックされた形で何百万という約束を生成しているにもかかわらず、コードは完全に同期してブロックされています。イベントループに到達しないため、ブロックされています。

は、この例を考えてみましょう:

var a = 0, b = 10000000; 

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

numbers(); 

これは非常に簡単です - あなたは千万番号を印刷したいです。しかし、あなたがそれを実行すると、それは非常に奇妙な動作をします。たとえば、数字をある点まで出力してから数秒間停止した後、スワップを使用している場合はゴミ箱に移動します。ここで何が起こっている

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

メインスレッドがオブジェクトを作成し続ける同期ループ内でブロックされているが、GCはそれらを解放する機会を持っていないということです:私はちょうど右の番号8486を見た後です。

このような長時間実行するタスクでは、作業を分割してしばらくの間イベントループに入る必要があります。ここで

は、あなたがこの問題を解決する方法である。

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の束にし、それループ。

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

出力の$(which time) -v node numbers1.js 2>&1 | egrep 'Maximum resident|FATAL'それはメモリの1.5ギガバイトを使用して墜落しました。 $(which time) -v node numbers2.js 2>&1 | egrep 'Maximum resident|FATAL'

Maximum resident set size (kbytes): 56404 

出力は、それはメモリの56メガバイトを使用して仕上げました。あなたが15Mの約束を作成する必要がある場合は

+0

1.私は何百万ものconsole.logを印刷しない... 1 ...最終結果...またははい - いくつかの時間...これまで10.000の反復... MAX 1000のconsole.logのようなものまであります。私のプログラムは大きなサーバーで滑らかに動作します。ラップトップ...それはメモリの問題に遭遇する...すべての '保留中の'データ/約束のために...しかし、私はこれをどのように最善の方法で解決するのだろうか? – PabloDK

+0

@PabloDK console.logは、収集されないオブジェクトを作成する操作の単なる例でした。いずれにしても、イベントループが実行されないようにすると、ノードで問題が発生します。通常は、タスクを小さなものに分割するソリューションがあります。私の更新された答えを見てください。あなたが何をやっているのか(数字や何かを計算していること)についてもっと説明したのですが、作成したコールバックをいくつかコンソールに出力したら、何をしたいのですか? – rsp

+0

私はポイントを得る...私はちょうど私のコードにいくつかのコミットを追加しました...あなたは私のコードを例として取ってください...どのように "分割"することが可能だろう - 全体を "破壊せずに"約束/解決声明の流れ?また、他の方法はありません - より良い/より速い方法で実行を最適化する方法はありません... "マルチスレッド"のように... 36コアを持つAmazonサーバーでは何が助けになるのでしょうか... ;-) – PabloDK