412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Иво Салмре » Программирование мобильных устройств на платформе .NET Compact Framework » Текст книги (страница 19)
Программирование мобильных устройств на платформе .NET Compact Framework
  • Текст добавлен: 18 июля 2025, 02:31

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


Автор книги: Иво Салмре



сообщить о нарушении

Текущая страница: 19 (всего у книги 69 страниц)

Определите модель памяти для вашего приложения

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

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

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

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

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

Как можно чаще контролируйте показатели, характеризующие работу вашего приложения

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

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

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

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

3. Используйте показатели производительности алгоритмов, генерируемые средой выполнения, а также установленными на устройстве средствами мониторинга работы приложении. Некоторые среды выполнения управляемого кода обеспечивают возможность измерения показателей, характеризующих отдельные аспекты функционирования приложений. В частности, они позволяют определить, сколько времени выполняется тот или иной код, а также отслеживать распределение памяти для размещения объектов и выполнение операций сборки мусора. Информация такого рода может пригодиться вам для настройки алгоритмов и выявления случаев утечки памяти. Наилучшей стратегией при проведении подобного рода анализа является как можно более полная изоляция кода, поведение которого анализируется. Самые точные и реальные характеристики производительности алгоритмов удается получить в тех случаях, когда имеется возможность вычленения интересующего нас фрагмента кода из тела программы, помещения его в отдельный проект с целью последующего выполнения для получения соответствующих показателей. Анализ такого рода оказывается полезным при сравнении эффективности различных алгоритмов. Современные средства мониторинга и отладки кода также способны предоставлять ценную информацию о том, на что расходуется процессорное время. Примечание. Более подробно этот вопрос рассматривается ниже в разделе "Получение информации об основных показателях производительности в .NET Compact Framework".

4. Используйте показатели производительности алгоритмов, генерируемые средствами мониторинга, которые доступны в настольных компьютерах и серверах. Для сред выполнения, функционирующих на настольных компьютерах и серверах, разработаны потрясающие средства, предназначенные для мониторинга работы управляемого кода. В настоящее время средства этой категории пока значительно опережают аналогичные им инструментальные средства, разработанные для устройств; вероятно, в течение некоторого времени такая ситуация будет сохраняться. Частично это объясняется тем, что рынок настольных компьютеров и серверов существует дольше, а частично – тем фактом, что в средах выполнения, предназначенных для настольных компьютеров и серверов, для поддержки утилит мониторинга могут выделяться гораздо большие объемы памяти. Можно ожидать, что в ближайшее время среды выполнения, используемые на устройствах, а вместе с ними и соответствующие средства получения эксплуатационных характеристик программ, получат дальнейшее развитие, однако по-прежнему будут уступать своим аналогам, ориентированным на настольные компьютеры и серверы. Поставляемые для настольных компьютеров и серверов средства, позволяющие анализировать работу приложений, способны обеспечивать получение детальной картины того, на выполнение каких функций приходится основная доля процессорного времени, и какие участки кода могут тормозить выполнение программ. Кроме того, современные средства мониторинга работы кода часто интегрируются в стандартные среды разработки приложений, что значительно упрощает проведение указанного анализа. Запуск кода, изначально предназначенного для устройств, в среде настольного компьютера или сервера позволит вам получить представление о возможностях его выполнения на этих платформах и глубже разобраться в особенностях его поведения в условиях устройств. Примечание. Имейте в виду, что механизмы JIT-компиляции, обработка исключений и стратегии сборки мусора для настольных компьютеров, серверов и устройств могут существенно отличаться друг от друга. Возможности настольных компьютеров и серверов в отношении доступных объемов памяти значительно превышают возможности мобильных устройств, а для каждого типа микропроцессоров существуют свои области вычислений, в которых он превосходит другие типы. Результаты мониторинга работы приложения, полученные на настольном компьютере или сервере, могут дать вам много полезной информации, но некоторые из характеристик приложения при выполнении на устройстве могут измениться. Подобные различия будут становиться особенно заметными тогда, когда в коде интенсивно используются операции файлового ввода-вывода, выполняется обмен данными по сети или обрабатывается графика, поскольку производительность кода в этих случаях будет в значительной мере зависеть от используемого оборудования и операционной системы. Инструментальные средства мониторинга, используемые на настольных компьютерах и серверах, помогут вам развить свою интуицию и глубже разобраться в особенностях распределения памяти для объектов, но окончательные выводы вы должны делать только на основании результатов, полученных при выполнении приложения на устройствах.

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

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

Получение информации об основных показателях производительности в .NET Compact Framework

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

• Суммарное время выполнения

• Количество объектов, размещенных в памяти в процессе выполнения кода.

• Количество операций по сборке мусора, произведенных в процессе выполнения кода.

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

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

Технические рекомендации относительно того, как активизировать генерацию рассматриваемых показателей времени выполнения, содержатся в статье "Developing Well Performing .NET Compact Framework Applications" ("Разработка высокопроизводительных приложений .NET Compact Framework") на Web-сайте http://msdn.microsoft.com.

На момент написания данной книги указанная статья располагалась по следующему URL-адресу:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/netcfperf.asp

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

Программа для измерения характеристик кода

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

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

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

using System;

internal class PerformanceSampling {

 //Значение этого параметра может быть задано произвольным, но количество

 //тестовых интервалов, равное 8, представляется достаточным для

 // большинства случаев

 const int NUMBER_SAMPLERS = 8;

 static string[] m_perfSamplesNames = new string[NUMBER_SAMPLERS];

 static int[] m_perfSamplesStartTicks = new int[NUMBER_SAMPLERS];

 static int[] m_perfSamplesDuration = new int[NUMBER_SAMPLERS];

 //Определить начальное значение счетчика тактов системных часов

 //для интервала

 internal static void StartSample(int sampleIndex, string sampleName) {

  m_perfSamplesNames[sampleIndex] = sampleName;

  m_perfSamplesStartTicks[sampleIndex] = System.Environment.TickCount;

 }

 //Определить конечное значение счетчика тактов системных часов

 //для интервала

 internal static void StopSample(int sampleIndex) {

  int stopTickCount = System.Environment.TickCount;

  //Счетчик тактов системных часов сбрасывается в ноль каждые 24,9 дня

  //(что соответствует примерно 2 миллиардам миллисекунд).

  //Эта маловероятная возможность будет принята нами во внимание

  if (stopTickCount >=m_perfSamplesStartTicks[sampleIndex]) {

   //Обычно будет выполняться этот код

   m_perfSamplesDuration[sampleIndex] = stopTickCount – m_perfSamplesStartTicks[sampleIndex];

  } else {

   //Значение счетчика тактов "перешло" через ноль,

   //и мы должны это учесть

   m_perfSamplesDuration[sampleIndex] = stopTickCount + (int.MaxValue – m_perfSamplesStartTicks[sampleIndex]) + 1;

  }

 }

 //Возвратить длительность тестового интервала

 //(в миллисекундах)

 internal static int GetSampleDuration(int sampleIndex) {

  return m_perfSamplesDuration[sampleIndex];

 }

 //Возвращает длительность истекшего тестового

 //интервала в секундах

 internal static string GetSampleDurationText(int sampleIndex) {

  return m_perfSamplesNames[sampleIndex] + ": " +

   System.Convert.ToString((m_perfSamplesDuration[sampleIndex] /(double) 1000.0)) +

   " секунд.";

 }

}

HA ЗАМЕТКУ

В документации по .NET Compact Framework утверждается, что интервал значений свойства .TickCount не может быть меньше 500 мс (0,5 секунды). Я обнаружил, что на практике достигается несколько лучшее разрешение (менее 100 мс, или 0,1 секунды), чем указанное. Вам придется немного поэкспериментировать самостоятельно. Если окажется, что вам необходим счетчик с более высоким разрешением, можете видоизменить приведенный выше код, включив в него системные вызовы операционной системы, управляющей собственным кодом, для получения доступа к низкоуровневым системным счетчикам. В большинстве случае возможностей приведенного выше кода вам должно быть вполне достаточно, а в силу своей простоты он оказывается удобным для использования в тех случаях, когда измерения требуется выполнить быстро.

Листинг 7.2. Тестовая программа, демонстрирующая использование приведенного выше кода для измерения временных интервалов

private void button1_Click(object sender, System.EventArgs e) {

 const int TEST_SAMPLE_INDEX = 2; //Выберите любое действительное

                                  //значение индекса

 //Начать измерение

 PerformanceSampling.StartSample(TEST_SAMPLE_INDEX, "TestSample");

 //Отобразить окно сообщений

 System.Windows.Forms.MessageBox.Show("Для прекращения измерения щелкните на кнопке OK");

 //Прекратить измерение

 PerformanceSampling.StopSample(TEST_SAMPLE_INDEX);

 //Отобразить результаты

 System.Windows.Forms.MessageBox.Show(PerformanceSampling.GetSampleDurationText(TEST_SAMPLE_INDEX));

}

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

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

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

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

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

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


    Ваша оценка произведения:

Популярные книги за неделю