KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Иво Салмре - Программирование мобильных устройств на платформе .NET Compact Framework

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Иво Салмре, "Программирование мобильных устройств на платформе .NET Compact Framework" бесплатно, без регистрации.
Перейти на страницу:

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

const int COUNT_UNTIL = 300;

const int LOOP_ITERATIONS = 40;

//---------------------------------------------------------

//HE ОЧЕНЬ ЭФФЕКТИВНЫЙ АЛГОРИТМ!

//

//Для имитации создания типичного набора строк используются

//обычные строки

//---------------------------------------------------------

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

 //Вызвать сборщик мусора, чтобы тест //начинался с чистого состояния.

 //ПРИБЕГАЙТЕ К ЭТОЙ МЕРЕ ТОЛЬКО В ЦЕЛЯХ ТЕСТИРОВАНИЯ! Вызовы

 //сборщика мусора в программах вручную будут приводить

 //к снижению общей производительности приложений!

 System.GC.Collect();

 int numberToStore = 0;

 PerformanceSampling.StartSample(0, "StringAllocaitons");

 string total_result = "";

 for (int outer_loop = 0; outer loop < LOOP_ITERATIONS; outer_loop++) {

  //Сбросить старый результат total_result = "";

  //Выполнять цикл до максимального значения x_counter, каждый

  //раз присоединяя очередную тестовую строку к рабочей строке

  for (int x_counter = 0; x_counter < COUNT_UNTIL; x_counter++) {

   total_result = total_result + numberToStore.ToString() + ", ";

   //Увеличить значение счетчика

   numberToStore ++;

  }

 }

 PerformanceSampling.StopSample(0); //Отобразить длину строки

 System.Windows.Forms.MessageBox.Show("Длина строки: " + total_result.Length.ToString());

 //Отобразить строку

 System.Windows.Forms.MessageBox.Show("Строка : " + total_result);

 //Отобразить длительность интервала времени, ушедшего на вычисления

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

}


//---------------------------------------------------------

//ГОРАЗДО БОЛЕЕ ЭФФЕКТИВНЫЙ АЛГОРИТМ!

//

//Для имитации создания типичного набора строк используется

//объект StringBuilder

//---------------------------------------------------------

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

 //Вызвать сборщик мусора, чтобы тест

 //начинался с чистого состояния.

 //ПРИБЕГАЙТЕ К ЭТОЙ МЕРЕ ТОЛЬКО В ЦЕЛЯХ ТЕСТИРОВАНИЯ! Вызовы

 //сборщика мусора в программах вручную будут приводить

 //к снижению общей производительности приложений!

 System.GC.Collect();

 System.Text.StringBuilder sb = new System.Text.StringBuilder();

 string total_result = "";

 int numberToStore = 0;

 PerformanceSampling.StartSample(1, "StringBuilder");

 for (int outer_loop = 0; outer_loop < LOOP_ITERATIONS; outer_loop++) {

  //Очистить объект StringBuilder (не создавая нового объекта)

  sb.Length = 0;

  //Очистить строку со старым результатом

  total_result = "";

  //Выполнять цикл до максимального значения x_counter, каждый раз

  //присоединяя очередную тестовую строку к рабочей строке

  for (int x_counter = 0; x_counter < COUNT_UNTIL; x_counter++) {

   sb.Append(numberToStore);

   sb.Append(", ");

   //Увеличить значение счетчика

   numberToStore++;

  }

  //Имитируем выполнение некоторых операций над строкой...

  total_result = sb.ToString();

 }

 PerformanceSampling.StopSample(1);

 //Отобразить длину строки

 System.Windows.Forms.MessageBox.Show("Длина строки: " + total_result.Length.ToString());

 //Отобразить строку

 System.Windows.Forms.MessageBox.Show("String : " + total_result);

 //Отобразить длительность интервала времени, ушедшего на вычисления

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

}


Таблица 8.3. Сравнение результатов (в секундах) для 40×300 циклов, выполненных с использованием эмулятора

Порядковый номер теста Неэкономное распределение памяти для строк Использование класса StringBuilder 1 25,475 0,85 2 25,225 0,925 3 24,5 0,875 Среднее 25,07 0.88 Экономия времени по сравнению с базовым уровнем 0% 96,5%

Таблица 8.4. Сравнение результатов (в секундах) для 40×300 циклов, выполненных на физическом устройстве Pocket PC

Порядковый номер теста Неэкономное распределение памяти для строк Использование класса StringBuilder 1 22,502 6,257 2 22,34 6,346 3 22,378 6,35 Среднее 22,41 6,32 Экономия времени по сравнению с базовым уровнем 0% 71,8%

Ниже представлен анализ полученных результатов.

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

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

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

Резюме

Разрабатывая схему управления памятью в приложении, важно анализировать, что происходит как на "макроскопическом" уровне приложения, так и на "микроскопическом" уровне алгоритма. Нa макроскопическом уровне важно иметь модель памяти, которая обеспечивает экономное потребление памяти устройства, но при этом позволяет вам держать под рукой данные и ресурсы, которые в вашем приложении используются наиболее часто. При решении этой задачи для ресурсов приложения вам может очень пригодиться подход, основанный на использовании конечного автомата. Что касается пользовательских данных приложения, то в этом случае целесообразно создать класс, предназначенный для управления объемом данных приложения, которые должны храниться в памяти в каждый момент времени. Этот класс будет играть роль инкапсулированного конечного автомата, которому известно, каким образом воспользоваться новыми данными, когда в этом возникает необходимость, или избавиться от устаревших данных, которые только напрасно занимают память. Обязательно вызывайте метод Dispose(), когда заканчиваете работу с объектами, для которых он предусмотрен; эта мера обеспечит принудительное освобождение неуправляемых ресурсов, удерживаемых объектом, и увеличит общую пропускную способность системы.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*