Чтение онлайн

на главную

Жанры

Программирование мобильных устройств на платформе .NET Compact Framework

Салмре Иво

Шрифт:

Сборка мусора в основном предназначена для решения двух задач: 1) восстановления памяти, которая больше не используется, и 2) уплотнения участков используемой памяти таким образом, чтобы для вновь распределяемых областей памяти были доступны как можно более крупные блоки. Тем самым решается одна из наиболее распространенных проблем, которая называется фрагментацией памяти. По своей сути эта проблема аналогична проблеме фрагментации дискового пространства. Если дисковое пространство периодически не реорганизовывать, то по прошествии некоторого времени оно дезорганизуется и разобьется на ряд чередующихся свободных и занятых участков небольшого размера; эти участки и являются фрагментами. Можно считать, что здесь мы имеем дело с проявлением действия закона увеличения энтропии применительно к дисковому пространству

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

Восстановление памяти является сравнительно несложным процессом. Выполнение кода временно прекращается, а активные (live) объекты (то есть объекты, к которым ваш код может осуществлять непосредственный или косвенный доступ) отыскиваются и рекурсивно помечаются. Так как остальные объекты, находящиеся в памяти, уже недоступны активному коду, они остаются непомеченными, что позволяет идентифицировать их как "мусор" и восстановить соответствующую память. Такая разновидность сборки мусора известна под названием "отслеживание и очистка" ("mark and sweep"). Обычно эта операция осуществляется довольно быстро.

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

Однако в рукаве у .NET Compact Framework наряду с JIT-компилятором, диспетчером памяти и сборщиком мусора спрятан еще один козырь: возможность очищать память от пассивного (dead) JIT-компилированного кода. Обычно это делать нежелательно, но при определенных обстоятельствах такая возможность становится незаменимой. Если уж исполнительный механизм, обеспечивая максимальную производительность, потрудился и выполнил JIT-компиляцию управляемого кода до собственных команд процессора, то отбрасывание JIT-компилированного кода могло бы показаться расточительством, поскольку когда в следующий раз возникнет необходимость в выполнении этого кода, то потребуется его повторная JIT-компиляция. В то же время, наличие такой возможности оборачивается благом в следующих двух случаях:

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

2. Когда набор хранящихся в памяти активных объектов становится настолько большим, что возникает риск аварийного завершения выполнения приложения, если для размещения дополнительных объектов, которые в соответствии с алгоритмом должны создаваться в ходе нормального выполнения приложения, не найдется достаточно большого

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

Краткий обзор методов управления памятью и сборки мусора

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

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

Рис. 3.2. Упрощенное схематическое представление состояния памяти приложения в процессе выполнения

Таблица 3.1. Условные графические обозначения, используемые на рис. 3.2, 3.3 и остальных рисунках

Фигура Описание
Темно-серые овалы Используемые в настоящее время объекты (например, объект Obj12 на рис. 3.2).
Белые овалы Пассивные объекты. Эти объекты (например, объект Obj6 на рис. 3.2) являются "мусором", к которому у приложения больше нет доступа и от которого можно избавиться с целью высвобождения дополнительной памяти.
Темно-серые прямоугольники Описания классов и типов, которые были загружены в память по той причине, что к типам осуществлял доступ выполняющийся код.
Внутренние прямоугольники Код, содержащийся в классах. (Код целиком находится внутри класса.)
Темно-серые внутренние прямоугольники Код, подвергнутый JIТ-компиляции, поскольку метод был вызван хотя бы один раз (например, код Code1 класса ClassXYZ на рис.3.2).
Светло-серые внутренние прямоугольники Код, который еще не подвергался JIТ-компиляции. По сравнению с прямоугольниками JIТ-компилированного кода эти прямоугольники имеют меньшие размеры, ибо еще не скомпилированные методы (например, метод Code4 класса XYZ на рис. 3.2) занимают в памяти очень мало места.

Приведенную на рис. 3.2 схему можно прокомментировать следующим образом:

■ Размеры отдельных элементов схемы выбраны таким образом, чтобы они давали представление об относительных объемах используемой памяти. Визуально большие классы и типы используют больше памяти по сравнению с визуально меньшими, поскольку содержат больше "начинки". Объекты различных типов используют различные объемы памяти. Пассивные объекты занимают память до тех пор, пока не будет выполнена операция сборки мусора. Методы, не подвергавшиеся JIТ-компиляции, занимают в памяти очень мало места.

■ В память загружаются описания всех типов и классов, которые используются в вашем приложении. Для различных типов и классов требуются различные объемы памяти.

■ JIT-компиляции подвергаются методы класса, которые вызывались хотя бы один раз. Пример: JIT-компиляции подвергались коды Code1, Code2, Code3 и Code7 класса ClassXYZ.

■ Те методы классов, которые еще не вызывались, не компилируются и поэтому не занимают много места в памяти. Пример: методы Code4 и Code5 класса XYZ еще не подвергались JIТ-компиляции. Как только они будут вызваны, будет осуществлена их JIT-компиляция и произведено распределение памяти для откомпилированного кода.

Поделиться:
Популярные книги

Прометей: повелитель стали

Рави Ивар
3. Прометей
Фантастика:
фэнтези
7.05
рейтинг книги
Прометей: повелитель стали

Гром над Академией Часть 3

Машуков Тимур
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Гром над Академией Часть 3

Уязвимость

Рам Янка
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Уязвимость

Войны Наследников

Тарс Элиан
9. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Войны Наследников

Законы рода

Flow Ascold
1. Граф Берестьев
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Законы рода

«Три звезды» миллиардера. Отель для новобрачных

Тоцка Тала
2. Три звезды
Любовные романы:
современные любовные романы
7.50
рейтинг книги
«Три звезды» миллиардера. Отель для новобрачных

Мимик нового Мира 13

Северный Лис
12. Мимик!
Фантастика:
боевая фантастика
юмористическая фантастика
рпг
5.00
рейтинг книги
Мимик нового Мира 13

Месть за измену

Кофф Натализа
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Месть за измену

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Не грози Дубровскому! Том 11

Панарин Антон
11. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том 11

Наваждение генерала драконов

Лунёва Мария
3. Генералы драконов
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Наваждение генерала драконов

Огненный князь 4

Машуков Тимур
4. Багряный восход
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Огненный князь 4

Мужчина не моей мечты

Ардова Алиса
1. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.30
рейтинг книги
Мужчина не моей мечты

Золушка по имени Грейс

Ром Полина
Фантастика:
фэнтези
8.63
рейтинг книги
Золушка по имени Грейс