С++ - язык, который изучается постепенно.ГЛАВА 14. Поблочное освобождение памяти

Недорогой но высококачественный сайт. Такое может быть? Да. У нас может быть всё. Достойное качество по доступной цене.
С точки зрения нашей студии создание сайта недорого значит, прежде всего, отменно, технологично и потом уже - недорого.
Удаленная форма работы с клиентами оптимизирует наши расходы и мы можем делать сайты по всему миру. Вам совсем не нужно приезжать к нам. Мы сэкономим Ваше время и средства.

В столь непростое время глобального финансового кризиса, когда отмирают старые схемы бизнеса, появляются новые. Самое лучше время для начала своей деятельности. Вы начинаете свой бизнес, а я помогу создать вам свой сайт очень недорого, для вас.
Огромной популярностью пользуются так называемые сайты-визитки.
Создание сайта-визитки - это совсем недорого, и будет по карману даже начинающему предпринимателю. При разработке подобного сайта достаточно небольшого бюджета.


По последним данным, на рынке продается по крайней мере 2 768 942 книги о С++, не говоря уже о всевозможных курсах, обучающих программах, журналах и семинарах с коктейлями. И все же в этом изобилии наблюдается удручающее однообразие. Просматривать полку книг о С++ в книжном магазине ничуть не интереснее, чем литературу по бухгалтерии. В сущности, все книги пересказывают одно и то же и отличаются разве что по весу и количеству цветов в диаграммах и таблицах.На сегодняшний день язык Си и языки основанные на синтаксисе Си (например, C++, Java, C#) наиболее популярны в практическом программировании. Язык Си имеет массу достоинств, он прост в изучении и лаконичен. Элементы языка Си (массивы, функции, указатели) максимально приближены к архитектуре компьютеров. Студия Web-дизайна, создание, раскрутка сайта

                    



Материалы книги получены с http://www.itlibitum.ru/

Поблочное освобождение памяти

Если выделение и освобождение памяти плохо влияет на быстродействие программы, иногда самое простое решение проблемы заключается в выполнении операций с блоками. Память выделяется снизу блока к его верху, а возвращается в систему сразу целым блоком (а не отдельными объектами).

Фиктивное удаление

Задача многих программ - побыстрее отработать свое и уйти. Это особенно справедливо в среде Unix, где сценарии оболочки объединяют множество крошечных, недолговечных программ. Нередко выделение памяти для новых объектов оказывается самым серьезным фактором, снижающим быстродействие таких программ. Простая стратегия оптимизации заключается в том, что вы выделяете память под объекты снизу вверх большого блока и не удаляете их.

struct Pool {

static Pool* gCurrentPool; // Пул для выделения памяти

enum { block_size = 8096 }; // Выберите свой любимый размер

unsigned char* space; // Следующая выделяемая область

size_t remaining; // Количество оставшихся байт в блоке

Pool() : space((unsigned char*)calloc(block_size, '\0')),

remaining(block_size) {}

void* Allocate(size_t bytes)

{

if (bytes > block_size)

return ::operator new(bytes); // Слишком большой запрос

if (gCurrentPool == NULL || bytes ? remaining)

gCurrentPool = new Pool;

void* memory = space;

space += bytes;

remaining -= bytes;

return memory;

}

};

class Foo {

public:

void* operator new(size_t bytes)

{

if (Pool::fCurrentPool == NULL)

Pool::gCurrentPool = new Pool;

return Pool::gCurrentPool->Allocate(bytes);

}

void operator delete(void*) {}

};

Быстрее некуда! Выделение занимает лишь несколько машинных тактов, а освобождение происходит мгновенно. Конечно, этот код не завоюет приза на олимпиаде по С++, но я видел, как он всего за несколько часов работы спасал проекты с серьезными проблемами быстродействия. Как минимум, он поможет определить, на что лучше направить усилия по оптимизации, поскольку выделение и освобождение памяти исключается из рассмотрения. Последовательно применяя его к разным классам, вы сможете установить, с какими классами связаны основные затруднения.

Обратите внимание, что для выделения блоков вместо операторной функции ::operator new используется функция calloc(). Большинство компиляторов С++ выделяет большой блок с помощью функции calloc() (или функции операционной системы), а затем управляет объектами в полученном блоке. Если использовать ::operator new для выделения блоков, скорее всего, дело кончится двойными затратами и двойной фрагментацией, поскольку эти блоки будут существовать в стандартных блоках менеджера памяти. При нашей стратегии лучше обойти ::operator new.

Описанная стратегия также хорошо работает в программах с более продолжительным сроком жизни, которые изначально создают множество объектов некоторого класса, но удаляют их относительно редко (если вообще удаляют). Если операторы new и delete перегружаются на уровне классов, то оптимизацию можно ограничить классами, обладающими указанным свойством.

Сборка мусора на уровне поколений

Многие алгоритмы выглядят примерно так:

void Eval(Structure s)

{

// Создать локальные объекты

Eval(s.SomePart()); // Произвести вычисления для подструктуры

// Удалить локальные объекты

}

Обход деревьев, вычисление рекурсивных выражений в языках типа Prolog - эти и многие другие рекурсивные алгоритмы имеют показанную структуру. Размещение локальных объектов в стеке может ускорить выделение и освобождение памяти, но этот вариант часто непрактичен. Альтернативный вариант - создать пул, локальный для Eval(), и уничтожить его целиком при выходе из Eval(). В области действия Eval() все временные объекты размещаются в этом пуле.

void* operator new(size_t size, Pool* p)

{

return p->Allocate(size);

}

template <class Type>

class PoolP { // Указатель, использующий пул

private:

Type* pointee;

public:

PoolP(Pool* p) : pointee(new(p) Type) {}

~PoolP { pointee->Type::~Type(); }

// Все остальное для ведущих указателей

};

void Eval(Structure s)

{

Pool p; // Объявляется в стеке!

PoolP<Foo> foo(&p); // Использует пул

Eval(s.SomePart()); // Использует свой собственный пул

f(p, s); // Вместо f(s); f будет использовать тот же пул

// Деструктор p уничтожает все сразу

}

Pool может представлять собой любую разновидность пула памяти. Скорее всего, это «тупой» пул, который просто выделяет память снизу вверх и не беспокоится о возвращении памяти. Умный указатель PoolP вызывает деструктор указываемого объекта, но не освобождает его память. На эту тему существует множество вариантов:

1.Обойтись без PoolP. Либо пусть пул сам вызывает деструкторы содержащихся в нем объектов из своего собственного деструктора (для этого все они должны иметь общий базовый класс и виртуальный деструктор), либо вообще не вызывайте деструкторы. (О господи! Неужели я сказал это? Но довольно часто такой вариант работает; главное - не хвастайтесь этим подвигом на семинарах по С++.)

2.Назначить «текущий пул» в глобальной переменной или статической переменной класса, а затем перегрузить оператор new для использования текущего пула, каким бы он ни был. При этом вам не придется передавать текущий пул всем подфункциям вроде упоминавшейся выше f().

3.Предоставить средства для перемещения или копирования объектов из локального пула в то место, где они смогут жить вне области действия Eval(). Эта тема выходит за рамки данной главы, а возможно, и книги, но для нее можно приспособить методику дескрипторов из следующей главы.

Последний вариант используется в стратегиях управления памятью настолько сложных, что голова начинает болеть заранее, еще до подробного знакомства с темой. К счастью, все трудности обусловлены необходимостью выбора - стоит или не стоит перемещать объекты из-за возможных обращений к ним со стороны чего-то, пережившего данный блок. Этот вопрос не из области С++, он скорее относится к алгоритмам и структурам данных.


Назад    Содержание    Далее    

   Почти всегда целью создания сайта является получение прибыли, которая в свою очередь, зависит от его внешнего вида. Статистика говорит, что около 94% людей, при выборе товара, сначала обращают внимание на упаковку, а потом уже на её содержимое. И если эта упаковка не привлекательная и безвкусная, мало кто обратит на нее внимание, и, соответственно, товар не будет пользоваться спросом.
   В случае с интернет, “упаковкой” выступает ваш сайт, а “товаром” - его контент. Если сайт выглядит непривлекательно, то каким бы ценным и нужным не было его содержимое, люди будут обходить его стороной. Наша задача - сделать ваш сайт привлекательным и удобным, чтобы люди чувствовали себя уютно и комфортно, чтоб они возвращались к вам еще и еще. Соответствие между ценой и качеством вас, несомненно, порадуют.
.
   Мы делаем сайты для бизнеса, а не красочную картинку, которая увешена тяжеловесными флэшами и огромными фотографиями.
   Пользователя, когда он попадает на абсолютно любой сайт, прежде всего интересует информация, затем, как реализовать на этом сайте полученную информацию, чтобы было удобно и просто (юзабилити), подбор цветовой гаммы, расположение блоков на странице и многое другое.

   Перед тем, как заказывать создание сайта, рекомендуем прочесть статью А зачем мне (нам) сайт? или Что нужно знать заказчику сайта
Да и вообще, обратите внимание на раздел Статьи о продвижении сайта и бизнеса там вы найдёте ответы на многие вопросы.