2017-05-10 3 views
1

私は64KBのの作品で16メガバイトのファイルを読み込み、それぞれの作品にBuffer.concatを行うと、後者は非常に遅くなることを証明するには、たくさん通過する全4Sをとります。スローBuffer.concat

Node.jsのバッファを連結する良い方法はありますか?

Node.jsバージョン使用:7.10.0、Windows 10(いずれも64ビット)。


以下の問題研究しながら、この質問は頼まれる:https://github.com/brianc/node-postgres/issues/1286、多くの聴衆に影響を与えます。

PostgreSQLドライバは、大量のbytea列を64Kbのチャンクで読み取り、それらを連結します。私たちは、Buffer.concatを呼び出すことが、そのような例でのパフォーマンスの大きな犠牲の背後にある原因であることを発見しました。

+0

なぜ64KB単位で読み込む必要がありますか?いずれの場合も、それを行うのに4秒かかるはずはありません。このコードを絞り込むことはできますか? – Brad

+0

@ブラッド私はちょうど説明を追加しました。 –

+2

各部分を配列に押し込み、全体で 'Buffer.concat()'を一緒に使います。コピーするO(n²)時間の代わりにO(n)。 – Ryan

答えて

1

毎回新しいバッファを作成するたびに連結するのではなく、バッファのすべての配列を保持し、最後に連結します。

Buffer.concat()は、バッファの全リストを取ることができます。その後、1回の操作で完了します。 https://nodejs.org/api/buffer.html#buffer_class_method_buffer_concat_list_totallength

+0

この戦略は、すべてのデータを読む前にすべてのデータを書き込む場合にのみ有効です。ストリームからデータを読み込んでいるときは、バッファの配列から正しいデータを抜き出すためのストラテジが必要です(これは乱雑になる可能性があります)。あるいは、パフォーマンスを向上させる必要があります(従来のソリューション)。この記事では、バッファ倍増の1つの説明があります。https://crntaylor.wordpress.com/2011/07/15/optimal-memory-reallocation-and-the-golden-ratio/ –

+0

@MatthewAmatoあなたは、バッファのあなたの配列から読み取ることができますいつでも。バッファーのサイズは一様であるため、実際にはチャンクが必要な場合は、その前に読み込む必要があります。その質問が16MBのチャンク全体を連結することを求めていることを考えれば、すべての作品が存在するまで待機していると思われます。 – Brad