web-dev-qa-db-ja.com

nodejsでのZipのマルチスレッド

NodejsでZipおよびunzip操作をマルチスレッド化できますか?

Yauzlのようなモジュールはたくさんありますが、どちらも複数のスレッドを使用せず、node-clusterなどで複数のスレッドを自分で開始することはできません。各Zipファイルは単一のスレッドで処理する必要があるためです。

8
Alex

Zlibのドキュメントによると

スレッドプールの使用:すべてのzlib APIは、明示的に同期されているものを除き、libuvのスレッドプールを使用します。これにより、一部のアプリケーションでは、パフォーマンスの低下(プールサイズを調整することで軽減できる)や、回復不能で壊滅的なメモリの断片化など、予期しない影響が生じる可能性があります。 https://nodejs.org/api/zlib.html#zlib_threadpool_usage

Libuvのスレッドプールによると、環境変数UV_THREADPOOL_SIZEを変更して最大サイズを変更できます

代わりに多くの小さなファイルを同時に圧縮したい場合は、ワーカースレッドを使用できます https://nodejs.org/api/worker_threads.html

もう一度質問を読むと、複数のファイルが必要なようです。ワーカースレッドを使用します。これらはメインスレッドをブロックせず、プロミスを介してそれらから出力を取得できます。

5
Strike Eagle

Node JSはLibuvとワーカースレッドを使用します。ワーカースレッドは、マルチスレッド方式で操作を実行する方法です。 libuvを使用することで(スレッドプールにスレッドを維持します)、デフォルトノードのjsサーバーのスレッドを増やすことができます。両方を使用して、操作のノードjsパフォーマンスを向上させることができます。

だからここにワーカースレッドの公式ドキュメントがあります: https://nodejs.org/api/worker_threads.html

ここでノードjsのスレッドプールを増やす方法を参照してください。 ノードjs 8のlibuvスレッドプールサイズを出力

2
Slim Coder

Node.jsでZipおよびunzip操作をマルチスレッド化できますか?

はい。

...複数のスレッドを自分で開始することはできません...各Zipファイルは単一のスレッドで処理する必要があるため

私はあなたの前提が間違っていると思います。なぜノードプロセスは複数のスレッドを開始できないと思いますか?これは、非常に成熟した node.jsクラスターモジュール を使用して実行しているアプリで、親プロセスがスーパーバイザーとして機能し、2つの子プロセスがネットワークとディスクI/Oにバインドされたタスクを頻繁に実行しています。

top output showing node.js processes using CPU threads

C列からわかるように、各プロセスは個別のスレッドで実行されています。これにより、ワーカープロセスがCPUまたはディスクにバインドされている間、マスタープロセスはコマンドおよび制御タスク(ワーカーのスポーン/リーピングなど)に対する応答性を維持できます。この特定のサーバーは、ネットワークからファイルを受け入れ、場合によってはそれらを解凍し、外部ファイルプロセッサ経由でファイルを送ります。 IOW、あなたが説明するような圧縮を含むそのタスク。

ドキュメントからのこのスニペット に基づいてワーカースレッドを使用するかどうかはわかりません。

ワーカー(スレッド)は、CPU集中型のJavaScript操作を実行するのに役立ちます。 I/O集約型の作業にはあまり役立ちません。 Node.jsの組み込み非同期I/O操作は、ワーカーよりも効率的です。

私には、その説明は「crypo!」と叫びます。過去には、高価なcrypo操作を実行する必要があるときに子プロセスを生成しました。

別のプロジェクトでは、ノードの child_process モジュールを使用して、圧縮するファイルのバッチがあるたびに新しい子プロセスを開始します。その特定のサービスは、process-me-2019.11.DD.MMのような名前の〜400ファイルのリストを参照し、それらを単一のprocess-me-2019-11-DDファイルに連結します。圧縮には時間がかかるため、新しいプロセスを生成すると、メインスレッドでのブロックが回避されます。

1
Matt Simerson

Helpノードjsでマルチスレッドを実行する方法。以下の3つのファイルを作成する必要があります

index.mjs

import run from './Worker.mjs';

/**
* design your input list of Zip files here and send them to `run` one file name at a time
* to Zip, using a loop or something. It acts as promise.
* exmaple : run( <your_input> ).then( <your_output> );
**/

Worker.mjs

import { Worker } from 'worker_threads';

function runService(id, options) {
    return new Promise((resolve, reject) => {
        const worker = new Worker('./src/WorkerService.mjs', { workerData: { <your_input> } });
        worker.on('message', res => resolve({ res: res, threadId: worker.threadId }));
        worker.on('error', reject);
        worker.on('exit', code => {
            if (code !== 0)
                reject(new Error(`Worker stopped with exit code ${code}`));
        });
    });
}

async function run(id, options) {
    return await runService(id, options);
}

export default run;

WorkerService.mjs

import { workerData } from 'worker_threads';

// Here goes your logic for zipping a file, where as `workerData` will have <your_input>.

それが役立つかどうか私に知らせてください。

1
Akshay

サードパーティのライブラリを使用するまで、純粋なNodejsでマルチスレッドを実行する方法はありません。 promiseを使用して、プロセスを並行して実行できます。ノードが使用するメインスレッドをオーバーロードしたくない場合は、RabitMQ(Redis Queue)を実装できます。独自のスレッドで実行されるため、メインスレッドがブロックされることはありません。

0
Sudhir Roy