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

Листинг 8.9. Сравнение эффективности использования строк и класса StringBuilder в алгоритмах

Листинг 8.9. Сравнение эффективности использования строк и класса StringBuilder в алгоритмах

Примечание. В этом примере используется класс 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 демонстрирует явное превосходство над методом, использующим распределение памяти для строк. В качестве грубого ориентира при сопоставлении алгоритмов можно руководствоваться тем, что тот алгоритм, который на эмуляторе, установленном на персональном компьютере, выполняется быстрее, окажется более быстрым и на мобильном устройстве; в то же время, если требуется более точная оценка, целесообразно всегда проводить тестирование производительности на физическом мобильном оборудовании.

Оглавление книги


Генерация: 2.682. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз