Программирование мобильных устройств на платформе .NET Compact Framework - Иво Салмре
Шрифт:
Интервал:
Закладка:
Работая с графическим кодом, вы должны хорошо представлять себе систематическую картину того, каким образом в приложении осуществляется визуализация изображений. При этом очень важно "не оказаться крохобором в мелочах, бездумно транжирящим крупные суммы" в обращении с ресурсами. Если имеются такие объекты Bitmap, Graphics, Pen, Brush, Font или ImageAttribute, которые будут использоваться во всех операциях рисования в приложении, то вы должны разработать систему, в задачи которой входит создание и кэширование указанных ресурсов. Применение предварительно создаваемых изображений сопряжено с дополнительным расходом ценной памяти, однако оно чрезвычайно ускоряет операции рисования; при разумном подходе это позволяет создавать приложения с привлекательным интерфейсом, сохраняющие высокую производительность. Исключайте случаи одновременной загрузки двух идентичных ресурсов — подобная расточительность никому не нужна.
Целесообразно также подумать над тем, нельзя ли представить приложение в виде таких различных состояний, чтобы распределение графических ресурсов или освобождение кэшируемых ресурсов, когда необходимость в них отпадает, можно было осуществлять для каждого состояния независимо от других.
Создание многофункциональных графических интерфейсов для мобильных устройств — вполне осуществимая задача, решение которой способствует повышению комфортности условий работы пользователя с вашим приложением. При построении графических пользовательских интерфейсов очень важно придерживаться подхода, являющегося одновременно творческим, аналитическим и систематическим. Сочетание творческого воображения художника, умеющего представлять себе то, чего еще не существует, аналитических способностей инженера, умеющего решать технические задачи, и проницательного взора бухгалтера, который не допустит неоправданных затрат, — вот что необходимо для того, чтобы ваше мобильное приложение было оценено конечными пользователями как высокопроизводительное, а взаимодействие с его привлекательным интерфейсом доставляло им одно удовольствие. Работа с графикой потребует от вас напряжения всех сил, но одновременно доставит огромное удовольствие; никогда не забывайте о производительности, и тогда выше вас — только небо!
ГЛАВА 12
Производительность: подведение итогов
Итоговые замечания по поводу производительности
Примите поздравления! Наконец-то вы добрались до конца части книги, которая посвящена вопросам производительности. Если вы внимательно читали весь предыдущий материал, то у вас сейчас должны быть все основания, чтобы чувствовать себя уверенно в отношении большинства аспектов программирования мобильных приложений, знание которых обеспечивает создание высокопроизводительного кода. Вы будете в состоянии самостоятельно исследовать возможные пути использования тех необычайных возможностей, которые предлагают мобильные устройства.
Поскольку тема производительности — многоплановая, она рассматривалась в предыдущих главах с самых различных сторон и с углублением в детали тех отдельных областей и уровней проектирования, которые оказывают на производительность мобильных приложений наиболее заметное влияние. Начало этому обсуждению было положено общим обзором аспектов производительности с точки зрения философии и практических методов проектирования.
Далее мы перешли к рассмотрению того, насколько выбор проектного решения может влиять на удачность или неудачность реализации обычных видов функциональности мобильных приложений, и познакомились с конкретными стратегиями, обеспечивающими достижение высокой производительности в этих областях. Теперь настало время подытожить все ранее сказанное о производительности, сведя все нити рассуждений в один пучок завершающих мыслей и практических рекомендаций, следование которым позволит вам действовать наилучшим образом.
Производительность и управление памятью
Ваши успехи в разработке мобильных приложений будут в огромной степени зависеть от того, каким образом вы организуете управление памятью как на микроскопическом, так и на макроскопическом уровнях. При проектировании модели использования памяти мобильного приложения и написании алгоритмов очень важно отдавать себе отчет в том, к каким действиям будет вынужден прибегать сборщик мусора в соответствии с теми или иными проектными решениями, которые вы примете. Хотя работу сборщика мусора вы непосредственно контролировать не можете, она заметно влияет на общую производительность приложений на основе управляемого кода.
С аналогичными трудностями сталкиваются и разработчики приложений на основе собственных кодов, однако они должны управлять памятью самостоятельно. Полная сборка мусора обходится недешево; чтобы восстановить память, занимаемую ненужными объектами, среда времени выполнения должна просмотреть все объекты высшего уровня, спускаясь вниз по деревьям подобъектов для отыскания всех объектов, которые по-прежнему используются приложением. Выполнение каждой операции по очистке памяти от "мусора" требует некоторых минимальных накладных расходов, объем которых зависит от количества объектов, которые необходимо просмотреть; многократное выполнение этой операции во многих случаях приводит к ощутимому замедлению работы приложений.
Частота выполнения сборки мусора напрямую зависит от того, насколько быстро ваш код расходует память приложения. Дефицит памяти в приложениях может быть обусловлен двумя факторами: 1) суммарным объемом поддерживаемого состояния приложения, включая всевозможные формы, глобальные объекты, пользовательские данные и любые другие объекты, содержащиеся внутри глобальных родительских объектов, и 2) временными объектами, которые создаются и разрушаются в процессе выполнения ваших алгоритмов. Если посмотреть на график изменения объема памяти, расходуемой приложением в процессе своего выполнения, то он будет иметь пилообразную форму. Высота зубьев этой пилы определяется тем, какой объем памяти вы оставляете для использования вашими алгоритмами, где имеется в виду память, не входящая в состав постоянно распределенной памяти приложения. Наклон же зубьев зависит от того, насколько эффективны процедуры распределения памяти для объектов, используемые в ваших алгоритмах. Чем более экономичны алгоритмы в отношении размещения новых объектов, тем более пологий наклон имеют зубья. В конечном счете, объем занимаемой приложением памяти начинает превышать некоторое пороговое значение, что приводит к запуску механизма сборки мусора, осуществляющего освобождение памяти от неиспользуемых объектов.
На рис. 12.1, 12.2, 12.3 и 12.4 проиллюстрированы четыре основных типа потребления памяти.
Рис. 12.1 схематически иллюстрирует поведение приложения в отношении потребления памяти в соответствии с наихудшим сценарием, который характеризуется высоким объемом постоянно распределенной памяти и неэкономным расходованием памяти в процессе работы алгоритмов. В этом случае постоянно распределенная память мобильного приложения занимает почти всю память, имеющуюся в системе. В результате этого в случае непрерывного размещения и уничтожения объектов, осуществляемого неэффективными алгоритмами, в памяти остается совсем мало места. Очень важно не забывать о том, что область памяти, занимаемая объектом, не может быть повторно использована сразу же после уничтожения ссылки на объект; чтобы восстановить память с целью сделать ее доступной для дальнейшего использования, должна быть выполнена операция сборки мусора. Непрерывное размещение и удаление объектов является причиной увеличения крутизны наклона зубьев пилообразного графика потребления памяти. Нехватка места для размещения объектов в памяти делает необходимой ее частую очистку от "мусора", что каждый раз сопровождается дополнительными накладными расходами.
В результате этого производительность резко ухудшается, поскольку сборщик мусора вынужден выполняться практически непрерывно, чтобы приложение могло хоть как-то работать.
Рис. 12.1. Наихудший случай: чрезмерное потребление памяти состоянием приложения, неэкономичные алгоритмы
На рис. 12.2 представлен промежуточный в отношении производительности случай. Хотя этому варианту поведения системы, как и предыдущему, также свойственно неэкономное размещение объектов в памяти алгоритмами приложения, тем не менее, объем постоянно распределенной памяти в этом случае гораздо меньше. Это означает, что, несмотря на то, что наклон линии, отображающей процессы непрерывного размещения и уничтожения объектов, остается крутым, имеется гораздо больше свободного пространства, способного дольше хранить "мусор". Таким образом, необходимость в сборке мусора будет возникать гораздо реже, в результате чего производительность значительно улучшается по сравнению с предыдущим случаем.