0

次のような出力を生成するサーバーがあります:http://192.168.0.1/getJPG= [ID]

ID1から20Mを通過する必要があります。

遅延のほとんどはファイルの保存にあることがわかります。現在、すべてのリクエスト結果を個別のファイルとしてフォルダーに保存しています。の形式:[ID] .jpg

サーバーの応答は速く、ジェネレーターサーバーは本当に高速ですが、受信したデータを迅速に処理できません。

後で処理するためにデータを保存する最良の方法は何ですか?

DBのように、SINGLEファイルのように、後で大きなファイルを解析するのと同じように、すべてのタイプの保存を行うことができます。

.NET、PHP、C++などでコーディングできます。プログラミング言語に制限はありません。ご意見をお聞かせください。

ありがとう

4

4 に答える 4

2

つまり、サーバーから2,000万個のファイルをダウンロードしていて、それらをディスクに保存できる速度がボトルネックになっているのでしょうか。インターネット経由でサーバーにアクセスしている場合、それは非常に奇妙です。おそらく、ローカルネットワーク経由でダウンロードしているのか、「サーバー」がローカルで実行されているのかもしれません。

保存するファイルが2,000万個あるので、すべてがRAMに収まらないと確信しているので、データをメモリにバッファリングしても効果はありません。また、データをディスクに書き込むことができる最大速度が本当にボトルネックである場合、MSSQLまたは他のDBを使用しても何も変わりません。DBには「魔法」はありません。他のプログラムと同じように、ディスクのパフォーマンスによって制限されます。

複数のディスクを使用するのが最善の策のようです。複数のファイルを並行してダウンロードし、それぞれが受信されたら、ラウンドロビン方式で別のディスクに書き込みます。ディスクが多ければ多いほど良いです。複数のスレッドまたは非ブロッキングI/Oを使用して、ダウンロードとディスク書き込みがすべて同時に行われるようにします。

于 2013-01-03T00:01:58.667 に答える
1

できるだけ早くできるだけ多くのコンテンツをダウンロードするアプリケーションを作成しようとしているようです。これを行うと、かなりの量の帯域幅やその他のリソースを消費するため、人々が気付く可能性があることに注意する必要があります。

これはWindows/NTFSであるため、次の点に注意する必要があります。-1つのフォルダに2kを超えるファイルを含めないでください。-可能な限り非同期/バッファ書き込みを使用します。-最高のI/Oパフォーマンスを得るために、利用可能な限り多くのディスクに分散します。

言及されていないことの1つは、ファイルサイズです。JPEGを取得しているように見えるので、平均ファイルサイズを約50kと想定します。

私は最近、.Net 4.0を使用して最大1KBのテキストファイルの無限のストリームでこのようなことを行い、ローカルネット上の100メガビットのネットワークコントローラーを飽和させることができました。TaskFactoryを使用してHttpWebRequestスレッドを生成し、データをメモリストリームにダウンロードしました。それらをメモリにバッファリングしたので、ディスクに書き込む必要はありませんでした。私がお勧めする基本的なアプローチは似ています-それぞれが要求を行うスレッドをスピンオフし、応答ストリームを取得して、それをディスクに書き込みます。最も難しい部分は、シーケンシャルフォルダとファイル名を生成することです。これを可能な限り迅速に実行し、スレッドセーフにし、メモリ内でブックキーピングを実行して、ディレクトリコンテンツの不要な呼び出しでディスクにアクセスしないようにします。

私はあなたの書き込みを順番に並べようとすることを心配しません。これを実行しようとするOS/NTFSの層は十分にあります。パイプの一部をすぐに飽和させる必要があります。

于 2013-01-03T08:09:22.603 に答える
1

これを効率的に行うために、アプリケーション(c ++)をマルチスレッド化します。

アプリケーションのメインスレッドは、これらのWebリクエストを作成し、それらをstd::listの後ろにプッシュします。これがメインのアプリケーションスレッドが行うすべてです。

pthread(Windowsでも、私の好みのスレッド方法...)をスポーンし(実行を続け、繰り返しスポーンしないでください)、whileループで同じstd::listをチェックするように設定します。ループでは、リストのサイズを確認し、処理するものがある場合は、リストから先頭の項目をポップします(これらは、ほとんどの場合、ミューテックスを必要とせずに別のスレッドで実行できます。 ..)そしてそれをディスクに書き込みます。

これにより、応答をメモリにキューに入れると同時に、ファイルをディスクに非同期で保存できます。サーバーが実際にあなたが言うほど速い場合は、メモリが不足する可能性があります。次に、処理するアイテムの数が特定のしきい値を超えている場合は、「待機」を実装しますが、これは、シリアルで実行するよりも少しだけ実行されます。

この速度を「改善」する実際の方法は、多くのワーカースレッド(それぞれが独自のstd :: listを持ち、「smart」が最小のアイテムまたは1つのstd :: listをミューテックスと共有してリストにプッシュする)を処理することです。ファイル。複数のハードドライブを備えたマルチコアマシンを使用している場合、これにより、これらのファイルをディスクに保存する速度が大幅に向上します。


もう1つの解決策は、ファイルの保存を多くの異なるコンピューターにオフロードすることです(現在のコンピューター上のディスクの数によって書き込みが制限されている場合)。ZMQ / 0MQなどのメッセージパッシングシステムを使用することで、現在稼働しているものよりも多くのハードドライブにアクセスできるさまざまなシステム(プル方式でセットアップされている)へのファイルの保存を非常に簡単に延期できます。 1台のマシン。ZMQを使用すると、ファンアウトアーキテクチャが組み込まれており、文字通り数分で実装できるため、ラウンドロビンスタイルのメッセージパッシングは簡単になります。


さらに別の解決策は、RAMディスクを作成することです(Linuxでネイティブに、Windows用に簡単に作成できます...私はこれを使用しました)。これにより、問題なく、必要な数のライターでファイルの書き込みを並列化できます。次に、再起動する前に、これらのファイルを実際の保存場所にコピーする必要があります。そうしないと、ファイルが失われます。ただし、実行中は、問題なくリアルタイムでファイルを保存できます。

于 2013-01-02T21:53:23.367 に答える
1

おそらく、ディスクに順番にアクセスするのに役立ちます。これを行う簡単なトリックは次のとおりです。すべての受信ファイルを非圧縮のZIPファイルにストリーミングします(そのためのライブラリがあります)。これにより、すべてのIOがシーケンシャルになり、ファイルは1つだけになります。また、10000枚程度の画像の後に新しいZIPファイルを分割して、個々のZIPを小さく保つこともできます。

後でZIPファイルからストリーミングしてすべてのファイルを読み取ることができます。圧縮されていないため、オーバーヘッドはほとんどありません。

于 2013-01-02T22:24:03.413 に答える