Появилась необходимость сделать контейнер объекта размер которого фиксирован,
но становится известен только в рантайме.
Понятно что в контейнере можно хранить указатели на объекты, но работа
с контейнером максимально критична к производительности, поэтому хочется
чтобы в контейнере хранился сам объект.
Вопрос: можно ли сделать такое при помощи аллокатора? Т.е. сделать некий dummy
класс который помещаем в контейнер, а аллокатор будет для этого класса выделять
реально необходимое количество памяти.
Здравствуйте, maq, Вы писали:
maq>Появилась необходимость сделать контейнер объекта размер которого фиксирован, maq>но становится известен только в рантайме. maq>Понятно что в контейнере можно хранить указатели на объекты, но работа maq>с контейнером максимально критична к производительности, поэтому хочется maq>чтобы в контейнере хранился сам объект. maq>Вопрос: можно ли сделать такое при помощи аллокатора? Т.е. сделать некий dummy maq>класс который помещаем в контейнер, а аллокатор будет для этого класса выделять maq>реально необходимое количество памяти.
Как-то ситуация осталась несколько неясной (для меня по крайней мере).
Что за контейнер?
Что именно подразумевается под "работа с контейнером максимально критична к производительности"?
Что за класс, объекты которого ты собираешься хранить? (И мне еще интересно, как это объекты одного класса могут иметь разные размеры, если это не шаблон класса.)
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, maq, Вы писали:
maq>>Появилась необходимость сделать контейнер объекта размер которого фиксирован, maq>>но становится известен только в рантайме. maq>>Понятно что в контейнере можно хранить указатели на объекты, но работа maq>>с контейнером максимально критична к производительности, поэтому хочется maq>>чтобы в контейнере хранился сам объект. maq>>Вопрос: можно ли сделать такое при помощи аллокатора? Т.е. сделать некий dummy maq>>класс который помещаем в контейнер, а аллокатор будет для этого класса выделять maq>>реально необходимое количество памяти.
B>Как-то ситуация осталась несколько неясной (для меня по крайней мере). B>Что за контейнер?
Например vector
B>Что именно подразумевается под "работа с контейнером максимально критична к производительности"?
Это значит что будут постоянные вставки/удаления в контейнер и очень нежелательно при этом все время
вызывать new/delete.
B>Что за класс, объекты которого ты собираешься хранить? (И мне еще интересно, как это объекты одного класса могут иметь разные размеры, если это не шаблон класса.)
Предположим класс у которого есть некие поля и часть переменного размера, но фиксированного для конкретного контейнера.
Собственно не хочется эту переменную часть все время создавать и удалять из кучи.
Если получится все это хранить в векторе, то он просто вырастет до определенного размера, а потом не будет обращений к куче.
Здравствуйте, maq, Вы писали:
maq>Предположим класс у которого есть некие поля и часть переменного размера, но фиксированного для конкретного контейнера.
maq>Собственно не хочется эту переменную часть все время создавать и удалять из кучи. maq>Если получится все это хранить в векторе, то он просто вырастет до определенного размера, а потом не будет обращений к куче.
Эээ, я так понимаю, что-то типа этого?
class c
{
int n_;
int* ptr_;
public:
c(int n) n_(n) { ptr_ = new int[n_]; }
~c() { delete [ptr_]; }
//copy ctor, operator =()...
};
Если это так, то можно например обернуть ptr_ умным указателем с подсчетом ссылок.
Или имеется ввиду что-то другое?
B>Если это так, то можно например обернуть ptr_ умным указателем с подсчетом ссылок. B>Или имеется ввиду что-то другое?
Собственно да, но умный указатель ничуть не лучше в плане производительности.
Ведь можно сделать так (грубо, не предусмотрено удаление, просто для примера чтобы было понятно):
class c
{
int n_;
int size_;
char offset_;
c(int n, int sz) : n_(n), size_(sz)
{
memset(&offset_, 0, size_);
}
public:
c* allocate(int n, int sz)
{
c* ptr = reinterpret_cast<c*>(malloc(size_of(c) + sz - 1));
new(ptr)c(n, sz);
}
}
В этом случае мы всего один раз выделяем память для объекта.
А в случае с вектором (если добъемся чтобы аллокатор создавал подобный объект),
размер которого заведомо больше — ни разу.
Re[3]: поможет ли аллокатор?
От:
Аноним
Дата:
11.02.04 12:15
Оценка:
Здравствуйте, maq, Вы писали:
maq>Это значит что будут постоянные вставки/удаления в контейнер и очень нежелательно при этом все время maq>вызывать new/delete.
Скорее всего хранение объектов (а не указателей) при постоянной вставке/удалении будет медленнее из за постоянного перераспределения памяти под эти объекты.
maq>>Это значит что будут постоянные вставки/удаления в контейнер и очень нежелательно при этом все время maq>>вызывать new/delete.
А>Скорее всего хранение объектов (а не указателей) при постоянной вставке/удалении будет медленнее из за постоянного перераспределения памяти под эти объекты.
Нет, так как в моем случае вставка указателя будет всегда сопровождаться аллокацией всего объекта
Re[5]: поможет ли аллокатор?
От:
Аноним
Дата:
11.02.04 13:14
Оценка:
Здравствуйте, maq, Вы писали:
maq>Нет, так как в моем случае вставка указателя будет всегда сопровождаться аллокацией всего объекта
что быстрее, вызвать new T + realloc(size() * sizeof(void*)) + memmov(size() * sizeof(void*)),
или realloc(size() * sizeof(T)) + memmov(size() * sizeof(T)) ???.
При больших размерах T выгоднее хранить указатели.
Здравствуйте, maq, Вы писали:
maq>Появилась необходимость сделать контейнер объекта размер которого фиксирован, maq>но становится известен только в рантайме.
Ээээ... что-то я не понял, нужно будет хранить объекты разных типов или одного типа?
maq>>Нет, так как в моем случае вставка указателя будет всегда сопровождаться аллокацией всего объекта
А>что быстрее, вызвать new T + realloc(size() * sizeof(void*)) + memmov(size() * sizeof(void*)), А>или realloc(size() * sizeof(T)) + memmov(size() * sizeof(T)) ???.
А>При больших размерах T выгоднее хранить указатели.
Понятно, забыл уточнить размер T порядка 100-200 байт.
Так что выгоднее хранить T.
maq>>Появилась необходимость сделать контейнер объекта размер которого фиксирован, maq>>но становится известен только в рантайме. AD>Ээээ... что-то я не понял, нужно будет хранить объекты разных типов или одного типа?
Одного типа, но размер которого известен только в рантайме
Не нравится мне что-то такая идея. А как быть с конструктором копирования и оператором присваивания?
Быть может стоит стоит определить в классе буфер подходящего размера — чтобы для всех возможных значений size подходил... (это если конечно значения этого самого size не сильно различаются, и можно допустить перерасход памяти).
Или сделать этот класс шаблонным...
Здравствуйте, maq, Вы писали:
maq>>>Появилась необходимость сделать контейнер объекта размер которого фиксирован, maq>>>но становится известен только в рантайме. AD>>Ээээ... что-то я не понял, нужно будет хранить объекты разных типов или одного типа?
maq>Одного типа, но размер которого известен только в рантайме
Как я уже сказал выше — это повлечет трудности при копировании таких объектов.
B>Не нравится мне что-то такая идея. А как быть с конструктором копирования и оператором присваивания?
С конструктором все нормально — переменная часть это POD структура, простое копирование
B>Быть может стоит стоит определить в классе буфер подходящего размера — чтобы для всех возможных значений size подходил... (это если конечно значения этого самого size не сильно различаются, и можно допустить перерасход памяти). B>Или сделать этот класс шаблонным...
Не получится. Размер передается как параметр COM объекту. Перерасход памяти допускать нельзя — будет создаватся
очень много таких объектов (миллионы)
Здравствуйте, maq, Вы писали:
B>>Не нравится мне что-то такая идея. А как быть с конструктором копирования и оператором присваивания? maq>С конструктором все нормально — переменная часть это POD структура, простое копирование
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, maq, Вы писали:
B>>>Не нравится мне что-то такая идея. А как быть с конструктором копирования и оператором присваивания? maq>>С конструктором все нормально — переменная часть это POD структура, простое копирование
B>Ой ли?
B>
Здравствуйте, maq, Вы писали:
maq>Проанализировал собственно я это дело, и пришел к печальному выводу: maq>аллокатор тут не поможет
maq>все дело в итераторах, они основываются на размере объекта для перемещения, maq>имеется в виду vector
maq>А жаль...
Т.е. my_allock выделяет память большими кусками, а потом раздает указатели на различные места большого куска в ответ на allocate. Ну и помечает блок как "свободный" в ответ на deallocate. Поскольку размер у тебя фиксированный, то реализуется все это дело достаточно просто.
Неплохой пример есть у Александреску, в главе про small object allocator.
maq>>Проанализировал собственно я это дело, и пришел к печальному выводу: maq>>аллокатор тут не поможет maq>>все дело в итераторах, они основываются на размере объекта для перемещения, maq>>имеется в виду vector
maq>>А жаль...
B>Быть может стоит попробовать такой вариант:
... skipped...
Это понятно — можно написать отптимизированный аллокатор для моего случая,
но к сожалению этот аллокатор не будет STL совместимый.
Здравствуйте, maq, Вы писали:
maq>Это понятно — можно написать отптимизированный аллокатор для моего случая, maq>но к сожалению этот аллокатор не будет STL совместимый.
Aлокатор my_alloc никакого отношения к STL (к аллокатору контейнера) не имеет, а посему не может быть "STL несовместимым". Для того, чтобы объект мог использоваться в качестве элемента стандартного контейнера необходимо, чтобы он был assignable и copy-constractible. Объекты класса holder этим требованиям удовлетворяют.
Так что я проблемы не вижу.