Лучшие контейнеры STL, чтобы избежать фрагментации кучи

У меня есть программа, которая анализирует 150000 файлов. Valgrind сообщает об отсутствии утечки памяти, но программа со временем замедляется.

Некоторые проблемы были связаны с слишком частым использованием std :: string и mktime, который занимал слишком много времени. (увидеть C ++ замедляет чтение 70000 файлов)

Но это все еще замедляется со временем. 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 — список уникальных строк, содержащих 150000 путей.
Я выбрал std :: set, потому что он автоматически обрабатывает дубликаты и автоматически поддерживает порядок сортировки.
Нет произвольного доступа, только добавлять записи, сортировать их (вручную или автоматически) и перебирать их.

fileInfoMap — массив структур с ключом time_t timestamp, соответствующим дате файла.
Я выбрал std :: map. Он также будет иметь 150 000 записей, поэтому занимает много памяти.
Нет произвольного доступа, только добавить записи на одном конце. Нужно перебрать их и, если необходимо, удалить записи из середины.

eventList — небольшой список «событийных» структур, скажем, 50 наименований.
Я выбрал std :: vector. Не уверен, почему на самом деле.
Нет произвольного доступа, только добавить записи в один конец, а затем итерации по коллекции.

Я довольно новичок в C ++. Спасибо за внимание.

0

Решение

Что касается управления памятью, контейнер принадлежит двум большим семействам: одно, которое выделяет все элементы вместе, и другое, которое выделяет элементы отдельно.

vector и deque принадлежат первому семейству, списку, множеству и сопоставляются со вторым.

Фрагментация памяти возникает, когда элементы постоянно добавляются и удаляются из контейнера, который не поддерживает глобальное перемещение.

Одним из способов избежать этой проблемы является использование vectors, используя «reserve«Чтобы предвидеть память, необходимо уменьшить перемещение и сохранить данные отсортированными при вставке.

Другой способ — использовать «контейнер, основанный на связывании» (например, список, набор и т. Д.), Предоставляя им распределитель, который выделяет память из больших кусков, перерабатывая их вместо вызова необработанного malloc / free для каждого отдельного элемента вставки / удаления.

Посмотри на станд :: распределитель

Вы можете легко написать распределитель, производя от std :: allocator и переопределяя allocate/deallocate функции, добавляющие всю необходимую логику и передавая yourallocator в качестве необязательного параметра шаблона контейнера, который вы хотите использовать.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]