Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Прочая околокомпьтерная литература » Основы объектно-ориентированного программирования - Бертран Мейер

Основы объектно-ориентированного программирования - Бертран Мейер

Читать онлайн Основы объектно-ориентированного программирования - Бертран Мейер

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 83 84 85 86 87 88 89 90 91 ... 188
Перейти на страницу:

Сборка мусора

Наиболее общей и полностью удовлетворительной техникой является лишь автоматическая сборка мусора или просто сборка мусора.

Механизм сборки мусора

Сборщик мусора (garbage collector) - это функция исполнительной системы (runtime system) языка программирования. Сборщик мусора выполняет обнаружение и утилизацию недостижимых объектов, не нуждаясь в управлении приложением, хотя приложение может иметь в своем распоряжении различные средства контроля работы сборщика.

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

Требования к сборщику мусора

Сборщик мусора, несомненно, должен быть корректным, удовлетворяя двум требованиям:

Свойства сборщика мусора

Качественность: каждый собираемый объект должен быть недостижимым.

Полнота: каждый недостижимый объект должен быть собран.

Качественность - абсолютное требование: лучше не собирать мусор, чем выбрасывать нужный объект. Нужна полная уверенность в том, что управлению памятью можно слепо доверять. Фактически надо забыть о нем почти навсегда, будучи уверенным, что кто-то как-то убирает беспорядок в вашей программе, также как кто-то как-то убирает мусор в вашем офисе, когда вас нет, но не убирает при этом ваши книги, компьютер и семейные фотографии со стола.

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

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

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

Определение качественности высвечивает трудности, связанные со сборкой мусора для некоторых языков программирования, и соответствующие роли языка и его реализации. Почему, например, сборка мусора обычно неприменима для С++? Обычно приводимые причины связаны с культурой: в мире С каждый разработчик должен сам заботиться о своих "игрушках" (по словам Стефенсона); он просто не доверяет какому-либо автоматическому механизму управлять его делами. Но, если бы это было действительной причиной, а не апостериорным оправданием, среды С++ могли бы, как минимум, предложить сборку мусора как подключаемую возможность, но большинство реализаций этого не делают.

Действительная проблема лежит в структуре языка, а не в технологии компиляции или культурных традициях. Язык С++, следуя С, слабо типизирован; он предоставляет возможность преобразования типа, благодаря которой на объект одного типа можно ссылаться как на сущность другого типа. Конструкция:

(OTHER_TYPE) x

означает, что теперь x рассматривается как сущность типа OTHER_TYPE, связанного или несвязанного с истинным типом x. Хорошие книги по С++ предостерегают приложения от применения подобных конструкций. Но разработчикам компилятора деваться некуда, - они обязаны реализовать язык в соответствии с его определением. Теперь представьте следующий сценарий. Ссылка на объект какого-либо полезного типа, скажем NUCLEAR_SUBMARINE, временно приведена к типу integer. Сборщик мусора, работающий в этот момент, не видит ссылки, а видит только целое типа integer. Не находя других ссылок на объект, сборщик утилизирует подлодку. Когда, через некоторое время программа выполнит обратное преобразование целого в ссылку типа NUCLEAR_SUBMARINE, будет уже поздно, - подлодка уничтожена.

Для решения этой проблемы предлагались разные методы. Широкого применения они не получили из-за накладываемых ограничений. Язык Java может рассматриваться как язык семейства C++, в котором введены существенные ограничения на систему типов, вплоть до удаления множественного наследования и универсализации, чтобы сделать, наконец, возможной сборку мусора в мире программ, основанных на С.

При тщательно спроектированной системе типов, конечно, можно сочетать мощь множественного наследования и универсализации с безопасностью типов и поддержкой эффективной сборки мусора.

Основа сборки мусора

Рассмотрим работу сборщика мусора.

Основной алгоритм включает две фазы: пометка и чистка. Фаза пометки, начиная с оригиналов, рекурсивно следует ссылкам, проходит активную часть структуры и помечает как достижимые все встреченные объекты. Фаза чистки обходит всю структуру объектов, утилизируя все не помеченные объекты и удаляя все пометки. (Об оригиналах см. раздел "Достижимые объекты в ОО-модели этой лекции.")

Как и в случае с подсчетом ссылок, объекты включают дополнительное поле, используемое здесь для пометки. Но требуемая для этого поля память незначительна, - достаточно одного бита для каждого объекта. Как будет видно при изучении динамического связывания, реализация ОО-возможностей требует, чтобы объект имел дополнительную внутреннюю информацию (например, тип). Эта информация обычно занимает одно или два слова в каждом объекте. Бит пометки может быть частью служебного слова, и не будет занимать дополнительную память.

Сборка по принципу "все-или-ничего"

Когда нужно приводить в действие сборщик мусора?

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

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

Но сборка мусора по принципу "все-или-ничего" имеет серьезный недостаток: полный цикл пометки-чистки может занять много времени - особенно в среде виртуальной памяти, большое пространство виртуальных адресов которого сборщик мусора должен обойти полностью, прерывая на это время выполнение приложения.

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

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

Даже в менее жизненно важных приложениях, таких как интерактивные системы, неприятно использовать инструмент, например, редактор текста, который иногда непредсказуемо зависает на 10 минут, потому что у него начался цикл сборки мусора.

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

1 ... 83 84 85 86 87 88 89 90 91 ... 188
Перейти на страницу:
На этой странице вы можете бесплатно скачать Основы объектно-ориентированного программирования - Бертран Мейер торрент бесплатно.
Комментарии