У меня есть программа, которая анализирует 150 000 файлов. Valgrind не сообщает об утечке памяти, но программа со временем замедляется.
Некоторые проблемы были связаны со слишком частым использованием std::string и слишком длительным использованием mktime. (см. С++ замедляет чтение 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++. Спасибо за внимание.