#c #vector
#c #вектор
Вопрос:
Я часто сталкиваюсь со случаем, когда я знаю, что std::vector
после выполнения работы a будет содержать максимальное количество элементов; скажем, 10000. Однако он может легко содержать гораздо меньше элементов, например, 100. Невозможно определить, сколько элементов будет получено .emplaced_back(...)
.
Конечно, если есть 10000 вызовов для возврата, вектор будет перераспределяться несколько раз. Но намного меньше, если вставлено всего 100 элементов.
Мой вопрос в том, будет ли вызов .reserve(10000)
плохим? Является ли выделение памяти чем-то, что требует «линейной» работы, или оно даже постоянное и, следовательно, не окажет негативного влияния, даже если большая часть вектора не используется? Какие важные моменты следует учитывать в этом случае?
Некоторое время назад я провел некоторое профилирование, в результате чего использование reserve(someIntermediateNumer)
может иметь преимущества. Однако результаты были не совсем убедительными, поскольку моя программа на самом деле не детерминирована (я тестировал на реальном коде). Мой интерес к этому частично также связан с теорией.
Комментарии:
1. Вам следует выполнить некоторый статистический анализ вашего поведения во время выполнения.
2. У вас больше шансов иметь меньший или больший вектор?
3. Сколько премиального адресного пространства?
4. en.cppreference.com/w/cpp/container/vector/reserve это «самое большее линейно». Если вы не заботитесь о «потерянной» памяти, это не повредит.
5. Не беспокойтесь о сжатии, чтобы соответствовать, если вам не нужна память обратно. В любом случае это может ничего не сделать.
Ответ №1:
В std::vector резерв (< большое число >) выполняет не больше работы, чем резерв (< небольшое число >).) . В обоих случаях выполняется однократное выделение памяти. Отрицательный эффект находится где-то в другом месте; например, поскольку ваше приложение использует больше памяти, это может привести к замене в какой-то момент.
Ответ №2:
производительность std::vector может зависеть от вашего конкретного распределителя памяти. Предполагая linux, это может быть один системный вызов или даже все пространство пользователя для некоторых реализаций, зависит от доступной в данный момент памяти. Сторона ядра может быть другой, потому что есть большая вероятность, что небольшой блок памяти уже находится в кэше, в то время как большой размер запросит дополнительную арену с помощью sbrk или mmap. Кроме того, ошибки и замены страниц, скорее всего, могут повлиять на больший фрагмент, но это произойдет позже при использовании.
И обратите внимание, что все вышесказанное предполагает, что резерв действительно запрашивает память. Потому что в некоторых реализациях может быть уже выделено достаточно места в конструкторе, чтобы игнорировать ваш запрос.