контейнер со стеком и динамическим размещением

0

Существует ли контейнер, который использует локальный буфер для небольшого количества элементов, и использует распределение кучи только тогда, когда количество элементов превышает определенный предел? Как и в большинстве реализаций std::string.


Фон

Контейнер используется в следующем (упрощенном) контексте:

Foo foo;                     // some data
vector<HandlerPtr> tagged;   // receives "tagged" items

// first pass: over all items in someList
for each(HandlerPtr h in someList)
{
  h->HandleFoo(foo);         // foo may become tagged or untagged here
  if (foo.Tagged())
    tagged.push_back(h);
}
for(auto itr=tagged.rbegin(); itr!=tagged.end(); ++itr)
{
  // ...
}

Эта часть кода имеет высокую частоту вызова, но пометка элемента довольно редка, количество элементов в someContainer обычно низкое, но несвязанное. Я не могу использовать предварительно выделенный "более глобальный" буфер. Цель состоит в том, чтобы избежать частого распределения.


Частота вызовов

  • Общее: ни один элемент не помечен. std::vector отлично
  • Общий: только один из нескольких элементов становится помеченным. вызывает высокочастотное распределение Я хочу избежать
  • Очень редко, но нужно поддерживать: someList растет во время первого прохода, количество элементов не предсказуемо, но все еще низкое.
  • 0
    Вы хотите использовать статические или стековые выделения? Для размещения стека см. Stackoverflow.com/questions/354442/…
  • 0
    @nimrodn: выделение стека, вероятно, лучшее описание того, что я хочу (фиксированный заголовок). т.е. ограниченное количество элементов, которые могут быть сохранены в экземпляре контейнера (без дополнительного выделения), и использование выделения кучи, если этого недостаточно.
Показать ещё 1 комментарий
Теги:
optimization
containers
stl

2 ответа

3

Нет стандартного контейнера, который гарантирует такое поведение. Однако, если вы это сделаете, вы можете создать настраиваемый STL-совместимый класс распределителя, который извлекает из небольшого стекового буфера для небольших распределений и выполняет только распределение кучи, когда запрошенный размер распределения превышает размер буфера стека. Вы можете подключить свой собственный класс распределителя как второй параметр шаблона для std::vector<T, Alloc>.

Для получения информации о создании настраиваемого распределителя вы должны прочитать эту статью.

  • 3
    Вы также можете попробовать .reserve () указать небольшой объем пространства в векторе, но его «достаточно» большую часть времени. Это потенциально позволит избежать перераспределения, если политика вашего вектора должна начинаться с размера 1 и использовать одну и ту же политику изменения размера независимо от текущего размера.
  • 1
    @Karl: Распространенный сценарий состоит в том, что контейнер останется пустым. Резервирование будет плохо для этого, так как оно всегда будет выделять динамическую память.
Показать ещё 1 комментарий
0

Хотя это не гарантируется, большинство std::string будут реализовывать Small String Optimization, что просто (с VС++ 10 таким образом сохраняется 8 или 16 символов)

Я не видел vectors делать это и всегда задавался вопросом, почему, но предстоящий стандарт С++ облегчит это с помощью std::aligned_storage и alignof. Таким образом, мы сможем получить правильно выровненную необработанную память и создать контейнеры с некоторым количеством "стековых" памяти по умолчанию.

  • 0
    Размер вектора обычно не больше, чем размер трех указателей. Сколько данных поместится в это пространство, учитывая, что вам также необходимо хранить некоторые служебные данные?
  • 1
    @visitor: Я думаю, это зависит от того, будете ли вы использовать старшие биты указателей для хранения таких данных :) Но я бы лично хотел иметь vector класс буфера. Стоимость копирования vector значительно отличается от стоимости копирования трех указателей, потому что это включает в себя динамическое выделение (то есть вызов для allocate ) и глубокое копирование существующих данных. Поэтому я решил, что было бы дешевле просто зарезервировать дополнительное место. vector<Element, 4> например. Однако я не знаю ни одного такого контейнера, но я, вероятно, попробую его дома, хотя всегда трудно соответствовать эффективности STL.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню