3

コールバックのデータに基づいて、別のファイルに書き込みたいコールバック関数を扱っています。

たとえば、ある呼び出しでは、january.csvに書き込みたい場合がありますが、別のデータを使用した別の呼び出しでは、代わりにjuly.csvになります。事前に決定されたシーケンスはありません。各コールバックの任意の月になる可能性があり、事前に知る方法がありません。january.csv(実際にはすべての月)は複数回書き込まれます。

これらのコールバックは非常に迅速に発生するため、このコードをできるだけ効率的にする必要があります。

私が取る素朴なアプローチは、毎回次のコードを使用することです。

ofstream fout;
fout.open(month_string);
fout<<data_string<<endl;
fout.close();

問題は、month.csvファイルを継続的に開いたり閉じたりしているため、これがあまり効率的ではないように見えることです。これをより速くするために、january.csv、february.csvなどを常に開いたままにしておくと言うことができるより速い方法はありますか?

編集:私はLinuxで/ dev / shmに書き込んでいるので、I/Oの遅延は実際には問題ではありません。

4

3 に答える 3

2

I / O呼び出しの数を減らすと同時に、呼び出すときにそれらを最大限に活用する必要があります。

たとえば、データをキャッシュし、ファイルに大きなチャンクを書き込みます。バッファをファイルに定期的にフラッシュする役割を担う別のスレッドが存在する可能性があります。

非効率性の根本は2つあります。ハードドライブが初期化されるのを待つ(速度を上げる)ことと、書き込むファイルと空のセクターを見つけることです。このオーバーヘッドは、書き込むデータの量に関係なく発生します。 。データのブロックが大きいほど、(プラッターが回転している間)効率的に書き込むためにより多くの時間が費やされます。これはフラッシュ/サムドライブにも当てはまります。サムドライブにはオーバーヘッドがあります(ロック解除、消去など)。したがって、目的は、大きなチャンクで書き込むことによってオーバーヘッドを削減することです。

データベースの使用を検討することをお勧めし ます。データベースの必要性の評価。

于 2013-03-19T15:16:19.417 に答える
0

ほとんどのシステムでは、一度に最大10,000個のファイルを開くことができるとは思えません。これにより、多かれ少なかれ、すべてのファイルを開いて、必要に応じてそれらに書き込むことができなくなります。

そのため、各ファイルのデータをバッファリングするために、おそらくプロキシ風のオブジェクトを作成する必要があります。バッファが特定のサイズを超えたら、ファイルを開き、データをディスクに書き込んでから、もう一度閉じます。

これに対する2つのかなり単純なアプローチを見ることができます。stringstream1つは、バッファとしてを使用して、ほとんどのコードを自分で作成することです。クライアントはオブジェクトにストリーミングし、オブジェクトは文字列ストリームに渡されます。次に、stringstreamが一定の長さを超えているかどうかを確認し、超えている場合は、コンテンツをディスクに書き込んでstringstreamを空にします。

もう1つのアプローチはsync、ファイルを開き、データを書き込み、ファイルを再度閉じるように実装する独自のファイルバッファオブジェクトを作成することです(通常、ファイルは常に開いたままになります)。

次に、それらをstd::map(またはstd::unordered_map)に格納して、ファイル名から一致するプロキシオブジェクトへのルックアップを実行できるようにします。

于 2013-03-19T15:24:16.307 に答える
0

同じファイルを何度も開いたり閉じたりするのにそれほど費用がかかるとは思いません。OSは通常、FSメタデータの一部をメモリにキャッシュすることでそのユースケースを処理するように設計されています。コストは主にシステムコールのコンテキスト切り替えです。一方、10kファイルでこれを行うと、OSのキャッシュ機能が使い果たされる可能性があります。

ターゲットで注釈が付けられたすべての出力を1つのファイルに順番に書き込んでジャーナルを形成することにより、FS作業の一部をオフロードすることができます。次に、別のプログラム(FS suppleant)は、そのジャーナルを開き、書き込みコマンドをバッファリングして(ファイルごとにグループ化)、バッファが特定のしきい値に達したときにディスクにフラッシュするタスクを実行します。ジャーナルで実行されたコマンドにコミット済みのタグを付ける必要があります。これにより、しなやかさが壊れて回復する必要がある場合に、実行すべきことが残っていることがわかります。


アップデート:

10000ファイルのオープンとキャッシュを同時にサポートするようにファイルシステムを調整し、コマンドのスケジューリングの問題に対処するためにファイルシステムを残すことができます(これがFSの目的です)。

問題は、ユースケースに適したファイルシステムを実際に選択することです。異なるFSでテストを実施し、どれが最もパフォーマンスが良いかを確認することをお勧めします。

残りの部分は、プログラムstd::map でファイル名を記述子に関連付けるために使用することだけです(簡単です)。

Linuxの最大オープンファイルの調整についてはSOを参照してください。または、特定のFSでファイルが見つからない場合は、そのトピックについて質問してください。

于 2013-03-19T15:24:23.147 に答える