2012-04-09 14 views
6

私は大量のデータを生成し、それをキューに入れて書き込みますが、問題はそのデータを私が現在書いているよりも速く生成しています(メモリを最大にして減速を開始する)。後でファイルを解析する予定があるので、注文は問題ではありません。メモリからファイルに大量のデータを書き込む最速の方法は何ですか?

私は少し見渡して、私の現在のプロセスを設計するのに役立ついくつかの質問を見つけました(でも私はまだそれが遅いと感じています)。 (私はEC2を使用していて、おそらくハードウェアの問題)私は多分、この間違ったを評価するので、私はプログラミングにかなり新しいです

//...background multi-threaded process keeps building the queue.. 
FileWriter writer = new FileWriter("foo.txt",true); 
     BufferedWriter bufferWritter = new BufferedWriter(writer); 
     while(!queue_of_stuff_to_write.isEmpty()) { 
      String data = solutions.poll().data; 
      bufferWritter.newLine(); 
      bufferWritter.write(data); 
     } 
     bufferWritter.close(); 

が、非常に迅速にキュー結果をダンプするためにあります。ここに私のコードは、これまでのところです私のアプローチが大丈夫なら、何とか改善することができますか?順序は関係ありませんので、複数のドライブ上の複数のファイルに書き込む方が理にかなっていますか?スレッディングは速くなりますか?など。私は、最良のアプローチとあらゆる提案がすばらしいとは確信していません。私の目標は、キューの結果を保存することです(申し訳ありません/ dev/null :-)に出力し、私のアプリのための可能な限り低いメモリ消費量を維持する(私は100%は確かではないが、キューは15ギガバイトを埋めるので15ギグ+ファイルになると仮定しています)。

Fastest way to write huge data in text file Java(私はバッファリングライターを使用する必要があります実現) Concurrent file write in Java on Windows(私は素晴らしいアイデアではなかったかもしれないマルチスレッドの書き込みいることがわかり製)

+0

私はCPUの速度>ハードドライブの速度を理解しているので、書き込みはおそらく処理に負けてしまうでしょう、私はちょうどhdスピードを手助けする方法を理解しようとしています。 –

+0

多くのものはあなたのボトルネックに依存します。私はあなたの帯域幅を最大限に活用していると思います(あなたの質問のように見えます)あなたのアカウントを最大限に活用することができます(コスト面で)。 –

+0

おおよその計算では、毎回15GBで4ドルがかかります。 –

答えて

2

そのコードを見ると、心に浮かぶのは文字エンコーディングです。あなたはストリングを書いていますが、最終的にストリームに行くバイトです。フードの下でライターの文字からバイトへのエンコーディング。これは、書き込みを処理している同じスレッドでそれをやっています。つまり、書き込みを遅らせるエンコーディングに費やされる時間があり、データが書き込まれる速度が低下する可能性があります。

単純な変更はBufferedOutputStreamなくBufferedWriter以上を使用し、代わりStringbyte[]のキューを使用してキューにプッシュスレッドに符号化を行い、そしてIOコードを持っているであろう。

これは、エンコードされたテキストが1文字あたり平均して2バイト未満を占める場合にも、メモリ消費を削減する可能性があります。ラテン文字とUTF-8エンコーディングの場合は、通常これが当てはまります。

しかし、IOサブシステムが処理できるデータよりも速くデータを生成している可能性が高いと思われます。IOサブシステムを高速化する必要があります。より高速なものを使用するか(EC2を使用している場合は、より高速なインスタンスをレンタルするか、別のバックエンドに書き込むか、SQSとEBSとローカルディスクかなど)いくつかのIOサブシステムを何とか並列に一緒に使用します。

0

私は限り、あなたは計算のうち、あなたのデータを生成し、そうであるように思います別のデータソースからデータをロードしない場合、データの生成よりも書き込みが常に遅くなります。

複数のスレッドでデータを複数のファイルに書き込むことができます(同じファイルではなく、同期の問題が原因です)。問題は解決しません。

アプリケーションの書き込み部分が終了して計算を続けるのを待つことは可能ですか?

もう1つの方法は次のとおりです。 キューを空にしていますか? solutions.poll()はソリューションキューを減らしますか?

0

複数のスレッドを使用して異なるファイルに書き込むことをお勧めします。また、コンストラクタから行うことができるBufferedWritersバッファサイズの設定について調べる必要があります。 10Mbのバッファで初期化し、それが役に立つかどうかを確認してください。

+0

それは?同じマシンのHDDに2つのファイルを並行して書き込むには、最初の書き込みを書き込むよりもずっと時間がかかります。 –

1

はい、複数のドライブに複数のファイルを書き込むと、同時にそのドライブに書き込むものがない場合は、I/Oがボトルネックではなくなるまで、ドライブの数に比例したパフォーマンスが必要です。パフォーマンスをさらに向上させるために、いくつかの最適化を試すこともできます。

巨大なファイルを生成していて、単にディスクを追い続けることができない場合は、GZIPOutputStreamを使用して出力を縮小し、ディスクI/Oの量を減らすことができます。非ランダムテキストの場合、通常、少なくとも2x-10xの圧縮率が期待できます。

//...background multi-threaded process keeps building the queue.. 
    OutputStream out = new FileOutputStream("foo.txt",true); 
    OutputStreamWriter writer = new OutputStreamWriter(new GZIPOutputStream(out)); 
    BufferedWriter bufferWriter = new BufferedWriter(writer); 
    while(!queue_of_stuff_to_write.isEmpty()) { 
     String data = solutions.poll().data; 
     bufferWriter.newLine(); 
     bufferWriter.write(data); 
    } 
    bufferWriter.close(); 

あなたが定期的に(すなわち、反復)データを出力している場合は、また別の出力形式への切り替えを検討する必要があります - 例えば、データのバイナリエンコーディング。データの構造によっては、データベースに格納するほうが効率的かもしれません。 XMLを出力していてXMLに固執したい場合は、EXIやFast InfoSetなどのBinary XML形式を調べる必要があります。

関連する問題