Эффективный буфер байт
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Здравствуйте.
Пишу программу, при этом стараюсь не использовать стандартную библиотеку (ради академического интереса). В одном из модулей мне требуется более-менее эффективный буфер байт.
Для реализации написал класс byte_buff (пока ещё не дописан):
byte_buff.h
byte_buff.cpp
Проверил код:
Время работы — 20,321 сек.
Собственно, решил сранить производительность с
std::vector
:Результаты, мягко говоря, меня удивили: время работы 0,04 сек. Такой производительности буфера я могу добится только увеличивая размер блока памяти до 0xFFFF, но врядли
std::vector
выделяет память такими блоками. Собственно вопрос: что такого добавляют в вектор, что он так быстро работает?Первое — используй
realloc
для увеличения размера блока. Он сам позаботится о копировании данных в другой блок памяти, если фрагментация не позволяет просто выделить новые ячейки в конце блока.По поводу блочного выделения памяти у
std::vector
, почитай эту статью http://alenacpp.blogspot.ru/2005/06/vector_30.html. Особенно, начиная с раздела «Коэффициент K».И посмотри исходный код самого
std::vector
. Уверен, много полезного встретишь.Для не POD типов можем получить кучу сюрпризов и потом долго искать ошибку.
porshe, давайте просто разберем хотя бы одну строчку из функции-члена add.
Возьмем только не тип char, а некоторый «тяжелый» класс someClass
Посмотрим также на стратегию расширения памяти. У Вас это
Судя по вызову
Память увеличивается на sizeof(someClass)*mem_block_size
То есть на постоянное значение.
В std::vector же, как правило, используются другие модели. Например,
при таком подходе сначала память будет выделяться малыми блоками, а потом запасы станут гигансткими.
Например вот: https://ideone.com/hPvkyq
Как видите, запас увеличился на 16000, а не на 16, т.е. Вашему вектору потребуется в 1000 раз больше перевыделений для заполнения такого участка.
А как это достигается? Путём вызова
std::malloc
?Croessmah, вроде в теме указано, что это буфер байт.
Если Вы посмотрите на объявление вектора
то увидите второй параметр — это аллокатор. Его задача выделять память по запросу. В векторе задается стандартный std::allocator<T>, но Вы можете его поменять на свой. Задача аллокатора — выделять и освобождать память.
После этого в выделенной памяти можно построить объект. Для этого можно использовать placement new (это отсыл к не долгому гуглению).
Например, в std::allocator есть функция-член
реализована она примерно так:
Память же выделяется в функции-члене allocate. Как внутри это делается — дело сугубо аллокатора. Стандартный, скорее всего, просто использует оператор new (не путать с new-выражением, это разные вещи).
Уничтожение объекта в функции-члене аллокатора
Естевственно, такое управление памтью очень эффективно и гибко, но в то же время намного сложнее, ведь необходимо «вручную» следить за созданием и уничтожением объектов (вызывать конструкторы и деструкторы) перед выделением и освобождением памяти.
Хм... может написать статью по аллокаторам?
Тогда смысл сравнивать его с std::vector?
Не указано как он будет использоваться.
Спасибо