150,000 個のファイルを分析するプログラムがあります。Valgrind はメモリ リークを報告しませんが、プログラムは時間の経過とともに遅くなります。
一部の問題は、std::string の使用頻度が高すぎたり、mktime に時間がかかりすぎたりすることに関連していました。( C++ が 70,000 ファイルの読み取りに時間の経過とともに遅くなる を参照)
しかし、それでも時間の経過とともに遅くなります。 Lotharyxは、コンテナーの使用がヒープの断片化を引き起こしていることを示唆しました。
さまざまな STL コンテナーの長所と短所に関するさまざまなフローチャートを読みましたが、よくわかりませんでした。
以下の疑似コードでは、ヒープの断片化を避けるために正しい選択をしたかどうか確信が持てません。
fileList.clear()
scan all disks and build "fileList", a std::set of file paths matching a pattern.
// filepaths are named by date, eg 20160530.051000, so are intrinsically ordered
foreach(filePath in fileList)
{
if (alreadyHaveFileDetails(filePath))
continue;
// otherwise
collect file details into a fileInfoStruct; // like size, contents, mod
fileInfoMap[time_t date] = fileInfoStruct;
}
// fileInfoMap is ordered collection of information structs of about 100,000 files
// traverse the list in order
foreach (fileInfo in fileInfoMap)
{
if (meetsCondition(fileInfo))
{
TEventInfo event = makeEventInfo()
eventList.push_back(event);
}
}
そして、上記のシーケンスは永遠に繰り返されます。
したがって、コンテナの選択のために、私は使用しました(または必要です):
fileList
-- 150,000 のパス名を含む一意の文字列のリスト。
std::set を選択したのは、重複を自動的に処理し、並べ替え順序を自動的に維持するためです。ランダム アクセスはなく、エントリを追加し、(手動または自動で) 並べ替え、それらを反復処理するだけです。
fileInfoMap
-- ファイルの日付に対応する time_t タイムスタンプをキーとする構造体の配列。std::map を選択しました。これも 150,000 エントリになるため、多くのメモリを占有します。ランダム アクセスはありません。一方の端にエントリを追加するだけです。それらを反復処理し、必要に応じて途中からエントリを削除する必要があります。
eventList
-- 「イベント」構造の小さなリスト、たとえば 50 項目。std::vector を選択しました。本当に理由がわからない。ランダムアクセスはありません。一方の端にエントリを追加するだけで、後でコレクションを反復処理します。
私はC ++にかなり慣れていません。ご検討いただきありがとうございます。