0

財務計算用の REST サービスを実装しています。したがって、各リクエストは CPU を集中的に使用するタスクであると想定されており、スレッドを作成するのに最適な場所は次の関数であると思います。

exports.execute = function(data, params, f, callback) {

    var queriesList = [];
    var resultList = [];

    for (var i = 0; i < data.lista.length; i++) 
    {
        var query = (function(cod) {

            return function(callbackFlow) {

                params.paramcodneg = cod;

                doCdaQuery(params, function(err, result)
                {
                    if (err) 
                    {
                        return callback({ERROR: err}, null);
                    }

                    f(data, result, function(ret)
                    {
                        resultList.push(ret);
                        callbackFlow();
                    });
                });
            }
        })(data.lista[i]);

        queriesList.push(query);
    }

    flow.parallel(queriesList, function() {
        callback(null, resultList);
    });
};

何が最適なのかわかりません。別のスレッドで flow.parallel を実行するか、queriesList の各関数を独自のスレッドで実行します。ベストは何ですか?そして、そのためにthreads-a-gogoモジュールを使用する方法は?

試してみましたが、そのための正しいコードを書くことができませんでした。

前もって感謝します。クレイソン・リオス

4

1 に答える 1

1

私は node.js に比較的慣れておらず、まだスレッドを使用したことはありませんが、マルチスレッド プログラミングの経験はある程度あるので、この質問に答えてみましょう。

単一のクエリごとにスレッドを作成する (これらのクエリは、データベースへの IO バウンドの呼び出しではなく、CPU バウンドの計算であると想定しています) ことはお勧めできません。コストのかかる操作でスレッドを作成および破棄するため、計算が必要なリクエストごとにスレッドのグループを作成して破棄すると、パフォーマンスが大幅に低下します。スレッドが多すぎると、プロセッサがスレッド間で切り替えるため、オーバーヘッドが増加します。プロセッサ コアより多くのワーカー スレッドを使用するメリットはありません。

また、各クエリの処理時間がそれほどかからない場合は、クエリの実行よりもスレッドの作成と破棄に多くの時間が費やされます。ほとんどの時間はスレッドのオーバーヘッドに費やされます。この場合、フローまたは非同期を使用するシングルスレッド ソリューションを使用する方がはるかに優れています。これにより、処理が複数のティックに分散され、node.js イベント ループが実行できるようになります。

シングルスレッド ソリューションは理解とデバッグが最も簡単ですが、クエリが原因でメイン スレッドが他の処理を実行できない場合は、マルチスレッド ソリューションが必要です。

あなたが提案するマルチスレッドソリューションはかなり良いです。すべてのクエリを別のスレッドで実行すると、メイン スレッドが停止するのを防ぐことができます。ただし、この場合、フローや非同期を使用しても意味がありません。これらのモジュールは、複数の node.js ティックに処理を分散することでマルチスレッドをシミュレートし、並行して実行されるタスクは特定の順序で実行されません。ただし、これらのタスクはまだ単一のスレッドで実行されています。独自のスレッドでクエリを処理しており、node.js イベント ループに干渉していないため、ループ内で次々と実行するだけです。すべてのアクションは node.js イベント ループのないスレッドで発生するため、flow または async を使用してもオーバーヘッドが増えるだけで、追加のメリットはありません。

より効率的な解決策は、スレッド プールをバックグラウンドでぶら下げて、そこにタスクをスローすることです。スレッド プールは、理想的にはプロセッサ コアと同じ数のスレッドを持ち、アプリケーションの起動時に作成され、アプリケーションのシャットダウン時に破棄されるため、コストのかかるスレッドの作成と破棄は 1 回だけ行われます。Threads a Gogo には、使用できるスレッド プールがあることがわかりましたが、残念ながら、私はまだ十分に慣れていないため、使用方法の詳細をすべて説明することはできません。

私はここでよく知らない領域に漂流していますが、各クエリを個別にグローバル スレッド プールにプッシュすることでそれを行うことができ、すべてのコールバックが完了したら完了だと思います。

Node.flow モジュールは、処理を高速化するためではなく、すべてのクエリ タスクとそのコールバックを管理するのに役立つため、ここで便利です。ループを使用して、flow.parallel(...) を使用して一連の並列タスクをフロー スタックにプッシュします。各タスクは、threadpool.any.eval() を使用してグローバル スレッドプールにクエリを送信し、ready を呼び出します。 () をスレッドプール コールバックで使用して、タスクが完了したことをフローに伝えます。並列タスクがキューに入れられたら、flow.join() を使用してすべてのタスクを実行します。これにより、スレッド プールでクエリが実行され、スレッド プールで一度にできるだけ多くのタスクが実行され、すべてのコアが使用され、スレッドの作成または破棄が回避され、すべてのクエリが処理されます。

他のリクエストも同様にタスクをスレッド プールに投入しますが、処理中のリクエストは、リクエストがスレッド プールに与えたタスクのコールバックしか取得しないため、気付かないでしょう。これはすべてメインスレッドで行われることに注意してください。スレッド プールは、すべての非メイン スレッド処理を行います。

gogo と node.flow のドキュメントを読んでいくつかのスレッドを実行し、いくつかの詳細を把握する必要がありますが、それで有利なスタートが切れるはずです。別のスレッドを使用することは、メイン スレッドを使用することよりも複雑であり、スレッド プールを使用することはさらに複雑であるため、最適なスレッドを選択する必要があります。余分な複雑さは、それだけの価値がある場合とそうでない場合があります。

于 2015-01-30T18:07:16.197 に答える