• Итоговые замечания по поводу производительности
  • Производительность и управление памятью
  • Производительность и многопоточное выполнение
  • Производительность и уровни абстракции API-интерфейсов
  • Связь производительности с организацией пользовательского интерфейса и работы с графикой
  • Старайтесь постоянно информировать пользователя о ходе выполнения приложения
  • Заключительные замечания и рекомендации
  • ГЛАВА 12

    Производительность: подведение итогов 

    Итоговые замечания по поводу производительности

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

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

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

    Производительность и управление памятью

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

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

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

    На рис. 12.1, 12.2, 12.3 и 12.4 проиллюстрированы четыре основных типа потребления памяти.

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

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

    Рис. 12.1. Наихудший случай: чрезмерное потребление памяти состоянием приложения, неэкономичные алгоритмы


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

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

    На рис 12.4 представлен наиболее оптимальный вариант расходования памяти.

    Рис. 12.2. Промежуточный случай: эффективно организованное состояние приложения, неэкономичные алгоритмы


    Рис. 12.3. Промежуточный случай: чрезмерное потребление памяти состоянием приложения, экономичные алгоритмы


    Рис. 12.4. Наиболее оптимальный случай: эффективное состояние приложения, и экономичные алгоритмы


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

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

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

    Производительность и многопоточное выполнение

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

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

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

    Производительность и уровни абстракции API-интерфейсов

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

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

    Идеальнее всего, если разработчику для загрузки и сохранения своих данных в виде XML-дерева удается использовать объектную модель документов (Document Object Model — DOM). Эта модель прекрасно подходит для работы с XML-данными среднего объема. Однако разработчики не должны забывать о том, что XML DOM в значительной мере основана на использовании состояний; при загрузке XML-данных в память они в действительности сохраняются в памяти в виде дерева объектов, представляющих XML-документ. В случае крупных документов создание такого дерева может приводить к дефициту памяти. В противоположность этому сама модель XML DOM строится поверх классов XMLReader и XMLWriter, которые не имеют состояния и осуществляют лишь однонаправленный доступ к данным; эти классы осуществляют синтаксический анализ или генерируют XML-данные, основываясь на состоянии лишь в самой минимальной степени. Эти классы удерживают в памяти ровно столько информации, сколько необходимо для того, чтобы иметь возможность осуществлять разбор XML-данных или записывать их в поток; они и не генерируют, и не используют хранящиеся в памяти деревья данных.

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

    Связь производительности с организацией пользовательского интерфейса и работы с графикой

    Первые и самые глубокие впечатления от вашего приложения конечные пользователи получают при знакомстве с его пользовательским интерфейсом и графикой.

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

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

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

    Графический код — это код, с помощью которого приложение может создавать рисунки. Эта возможность используется для представления нестандартных красочных изображений пользователям, а также для реализации высокоинтерактивных нестандартных элементов управления пользовательского интерфейса. Часто для интеграции графического кода в пользовательский интерфейс имеется несколько возможностей, начиная с простейших (например, отображение рисунков на элементах управления PictureBox), и заканчивая самыми сложными (например, создание нестандартных элементов управления). Выбор оптимальной модели встраивания графики в приложение имеет столь же важное значение, что и рассматривавшийся нами ранее выбор наиболее подходящего уровня абстракции API-интерфейсов; всегда старайтесь использовать самую простую из возможных моделей.

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

    Старайтесь постоянно информировать пользователя о ходе выполнения приложения

    Игнорируя проблемы производительности, вы накликаете на себя беду. Закрывать глаза на проблемы производительности, которые могут возникать в вашем приложении, и не замечать их — это самый верный способ создания самому себе трудностей в процессе дальнейшей разработки. Лучше всего разрешать проблемы производительности сразу же, как только они возникли, и именно в этот момент их легче всего диагностировать. В еще большей степени, чем приложения для настольных компьютеров, мобильные приложения можно рассматривать как состоящие из ряда способных блокировать друг друга взаимосвязанных систем, которые должны совместно использовать одни и те же системные ресурсы. Поскольку в случае мобильных устройств пул доступной памяти имеет гораздо меньший объем, а понятия свопинга редко используемых областей памяти в дисковый файл подкачки для них не существует, любой лишний элемент может стать причиной возникновения крупномасштабных проблем в рамках всего приложения..Так, хранение крупных растровых изображений в памяти непосредственно уменьшает ресурсы, которые можно было бы использовать для хранения дерева XML-данных или скомпилированного кода функции. Случаи, когда приложение исчерпывает всю доступную память, диагностировать легко. Установить источник проблем гораздо сложнее, если в приложении нехватка памяти нарастает постепенно, все чаще и чаще активизируя сборщик мусора, чтобы поддерживать приложение в работоспособном состоянии.

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

    Очень важно, чтобы в тех случаях, когда проблемы производительности уже проявились, вы не пытались расширять возможности мобильного приложения и добавлять в него новый код, питая ложные надежды на то, что в будущем у вас еще будет время заняться этими проблемами. Добавлять новые средства и код в приложение следует лишь тогда, когда вы располагаете резервами производительности для поддержки этих средств. Если вы чувствуете, что "уткнулись в глухую стену", то прежде, чем вводить в приложение дополнительные элементы, потребляющие ресурсы, попытайтесь сделать состояние приложения более экономичным и свести к минимуму алгоритмическую чехарду с созданием и уничтожением объектов. Дополнительные резервы производительности — это та валюта, которой вы сможете расплачиваться за новые возможности; если у вас есть долги, то сначала рассчитайтесь с ними и лишь после этого позволяйте себе дальнейшие траты.

    Заключительные замечания и рекомендации

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

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

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

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

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

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

    ■ Осмотрительно выбирайте размеры применяемых вами растровых изображений. В наши дни размеры обычных цифровых изображений значительно превышают те, которые еще допустимы при выводе изображений на экраны мобильных устройств. При больших размерах изображений вы будете напрасно терять время на их пересылку по сети, место, необходимое для их хранения на устройстве, и память, занимаемую ими при загрузке. Лишние 0,5 Мбайт данных изображения, загруженных в память, эквивалентны сотням или даже тысячам других удерживаемых в памяти элементов, не являющихся изображениями; 500 Кбайт пикселей по занимаемому объему равносильны 500000 целочисленных элементов данных. При любом удобном случае прежде, чем загружать изображение, уменьшайте его размеры, сообразуясь с возможностями экрана целевого устройства. Если это сделать невозможно или в память должны загружаться изображения с высоким разрешением, подумайте, нельзя ли сразу же создать в памяти копии этих изображений с низким разрешением, после чего уничтожить их объемистый в отношении используемой памяти оригинал, чтобы за приложением не было закреплено большое количество лишней памяти. 

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

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







     


    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх