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

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

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


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



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

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

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

Option Strict On

Imports System

Friend Class PerformanceSampling

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

'тестовых интервалов, равное 8, представляется достаточным для большинства

'случаев

Const NUMBER_SAMPLERS As Integer = 8

Private Shared m_perfSamplesNames(NUMBER_SAMPLERS) As String

Private Shared m_perfSamplesStartTicks(NUMBER_SAMPLERS) As Integer

Private Shared m_perfSamplesDuration(NUMBER_SAMPLERS) As Integer

'–

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

'–

Friend Shared Sub StartSample(ByVal sampleIndex As Integer, _

 ByVal sampleName As String)

 m_perfSamplesNames(sampleIndex) = sampleName

 m_perfSamplesStartTicks(sampleIndex) = System.Environment.TickCount()

End Sub

'–

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

'–

Friend Shared Sub StopSample(ByVal sampleIndex As Integer)

 Dim stopTickCountAs Integer = System.Environment.TickCount

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

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

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

 If (stopTickCount >= m_perfSamplesStartTicks(sampleIndex)) Then

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

  m_perfSamplesDuration(sampleIndex) = _

   stopTickCount – m_perfSamplesStartTicks(sampleIndex)

 Else

  'Значение счетчика тактов "завернулось" через ноль, и мы

  'должны это учесть

  m_perfSamplesDuration(sampleIndex) = stopTickCount + _

   (Integer.MaxValue – m_perfSamplesStartTicks(sampleIndex)) + 1

 End If

End Sub

'–

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

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

'–

Friend Shared Function GetSampleDuration(ByVal sampleIndex _

 As Integer) As Integer

 Return m_perfSamplesDuration(sampleIndex)

End Function

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

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

Friend Shared Function GetSampleDurationText(ByVal _

 sampleIndexAs Integer) As String

 Return m_perfSamplesNames(sampleIndex) + ": " + _

  System.Convert.ToString( _

  (m_perfSamplesDuration(sampleIndex) / CDbl(1000.0)) ) + " секунд."

End Function

End Class

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

Private Sub Button1_Click(ByVal senderAs System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 Const TEST_SAMPE_INDEXAs Integer = 2 'Выбрать любой допустимый индекс

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

 PerformanceSampling.StartSample(TEST_SAMPE_INDEX, "TestSample")

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

 MsgBox("Для прекращения измерения нажмите кнопку OK")

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

 PerformanceSampling.StopSample(TEST_SAMPE_INDEX)

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

 MsgBox(PerformanceSampling.GetSampleDurationText( _

  TEST_SAMPE_INDEX))

End Sub

Листинг 7.3. Демонстрация трех различных уровней организации обратной связи с пользователем

'Поместить надписи на кнопках

Private Sub Form2_Load(ByVal senderAs System.Object, _

 ByVal e As System.EventArgs) Handles MyBase.Load

 button1.Text = "Плохая обратная связь"

 button2.Text = "Хорошая обратная связь"

 button3.Text = "Улучшенная обратная связь"

End Sub

'–

'Пример слабых интерактивных возможностей интерфейса:

' – Визуальная индикация начала выполнения работы отсутствует

' – Визуальная индикация окончания выполнения работы отсутствует

' – Пользовательский интерфейс не способен к отклику в процессе работы

' – 0 завершении выполнения задачи пользователь вынужден только догадываться

'–

Private Sub Button1_Click(ByVal senderAs System.Object, _

 ByVal eAs System.EventArgs) Handles Button1.Click

 'Имитировать выполнение работы путем создания паузы продолжительностью

 '4 секунды

 System.Threading.Thread.Sleep(4000)

End Sub

'–

'Пример лучших интерактивных возможностей интерфейса:

' + Визуальная индикация начала выполнения работы

' (появление курсора ожидания)

' + Визуальная индикация окончания выполнения работы

' (исчезновение курсора ожидания)

' – Пользовательский интерфейс не способен к отклику в процессе работы

' + По завершении выполнения задачи конечный пользователь узнает об этом,

' а пользовательский интерфейс восстанавливает способность к отклику

'–

Private Sub Button2_Click(ByVal senderAs System.Object, _

 ByVal eAs System.EventArgs) Handles Button2.Click

 System.Windows.Forms.Cursor.Current = _

  System.Windows.Forms.Cursors.WaitCursor

 'Имитировать выполнение работы путем создания паузы продолжительностью

 '4 секунды

 System.Threading.Thread.Sleep(4000)

 System.Windows.Forms.Cursor.Current = _

  System.Windows.Forms.Cursors.Default

End Sub

'–

'Пример еще лучших интерактивных возможностей интерфейса:

' + Визуальная индикация начала выполнения работы

' (появление курсора ожидания)

' + Отображение дополнительного текста, сообщающего пользователю

' о том, что происходит

' + Визуальная индикация окончания выполнения работы

' (исчезновение курсора ожидания)

' – Пользовательский интерфейс не способен к отклику в процессе работы

' + По завершении выполнения задачи конечный пользователь узнает об этом,

' а пользовательский интерфейс восстанавливает способность к отклику

' + Текстовые сообщения информируют пользователя о том, что происходит

'–

Private Sub Button3_Click(ByVal senderAs System.Object, _

 ByVal e As System.EventArgs) Handles Button3.Click

 'Предоставить пользователю текст, информирующий его обо всем происходящем

 Label1.Text = "Ждите! Работа выполняется!"

 'Заставить ПИ обновить текст

 '(иначе он сделает это только тогда, когда будет перерисовывать сообщение,

 'а это может произойти и после выхода из данной функции)

 Label1.Update()

 'Отобразить курсор ожидания

 System.Windows.Forms.Cursor.Current = _

  System.Windows.Forms.Cursors WaitCursor

 'Имитировать выполнение работы путем создания паузы продолжительностью

 '2,8 секунды

 System.Threading.Thread.Sleep(2800)

 'Необязательное дополнительное обновление состояния

 Label1.Text = "Ждите! Работа близка к завершению!"

 Label1.Update()

 'Имитировать выполнение работы путем создания паузы продолжительностью

 '1,2 секунды

 System.Threading.Thread.Sleep(1200)

 'Известить пользователя текстовым сообщением о завершении работы

 '(текст обновляется всякий раз, когда ПИ выполняет обычное обновление

 'экрана)

 Label1.Text = "Работа успешно завершена!"

 'Избавиться от курсора ожидания

 System.Windows.Forms.Cursor.Current = _

  System.Windows.Forms.Cursors.Default

End Sub

Листинг 7.4. Сравнение производительности двух алгоритмов, в одном из которых используются исключения, а во втором – нет

'==================================================================

'Примечание. В этом примере используется класс PerformanceSampling,

' определенный ранее в этой главе. Убедитесь в том, что

' этот класс включен в проект

'ТЕСТОВАЯ ФУНКЦИЯ:

'Сложить n1 и n2 и возвратить результат

'в n3

' Возвращаемое значение:

' TRUE: если результат положителен

' FALSE: если результат отрицателен

'==================================================================

Function returnFalseIfLessThanZero_Add2Numbers( _

 ByVal n1As Integer, ByVal n2 As Integer, _

 ByRef n3 As Integer) As Boolean

 n3 = n1 + n2

 'Результат меньше 0?

 If (n3 < 0) Then

  Return False

 End If

 Return True

End Function

'========================================================================

'ТЕСТОВАЯ ФУНКЦИЯ:

'Сложить n1 и n2 и возвратить результат

'в n3

'Если n3 меньше 0, то функция ПЕРЕДАЕТ УПРАВЛЕНИЕ ОБРАБОТЧИКУ ИСКЛЮЧЕНИЙ.

'В противном случае возвращается TRUE

'========================================================================

Function exceptionIfLessThanZero_Add2Numbers( _

 ByVal n1As Integer, ByVal n2As Integer, _

 ByRef n3 As Integer) As Boolean

 n3 = n1 + n2

 'Результат меньше 0?

 If (n3 <0) Then

  Throw New Exception("Результат меньше 0!")

 End If

 Return True

End Function

'=======================================================

'Осуществляет многократные вызовы простой функции и

'измеряет общее время выполнения

'Вызываемая функция НЕ приводит к возбуждению исключений

'=======================================================

Private Sub buttonRunNoExceptionCode_Click(ByVal senderAs System.Object, _

 ByVal eAs System.EventArgs) Handles buttonRunNoExceptionCode.Click

 Const TEST_NUMBERAs Integer = 0

 Dim numberItterations As Integer

 numberItterations = _

  CInt(textBoxNumberAttempts.Text)

 'Отобразить количество итераций, которые предстоит выполнить

 ListBox1.Items.Add("=>" + numberItterations.ToString() + " итераций")

 Dim count_SumLessThanZero As Integer

 Dim dataOut As Integer

 '–

 'Запустить таймер

 '–

 PerformanceSampling.StartSample(TEST_NUMBER, "Исключения отсутствуют")

 '–

 'Выполнить цикл, в котором осуществляется вызов функции

 '–

 count_SumLessThanZero = 0

 Dim sumGreaterThanZero As Boolean

 Dim i As Integer

 While (i < numberItterations)

  '=========================

  'Вызвать тестовую функцию!

  '=========================

  sumGreaterThanZero = _

   returnFalseIfLessThanZero_Add2Numbers(-2, -3, dataOut)

  If (sumGreaterThanZero = False) Then

   count_SumLessThanZero = count_SumLessThanZero + 1

  End If

  i = i + 1

 End While

 '–

 'Остановить таймер

 '–

 PerformanceSampling.StopSample(TEST_NUMBER)

 '–

 'Показать результаты пользователю

 '–

 If (count_SumLessThanZero = numberItterations) Then

  MsgBox("Тест выполнен")

  ListBox1.Items.Add( _

   PerformanceSampling.GetSampleDurationText(TEST_NUMBER))

 Else

  MsgBox("При выполнении теста возникали осложнения")

 End If

End Sub

'==================================================

'Осуществляет многократные вызовы простой функции и

'измеряет общее время выполнения.

'Вызываемая функция ВОЗБУЖДАЕТ исключения

'==================================================

Private Sub buttonRunExceptionCode_Click_Click(ByVal senderAs System.Object, _

 ByVal e As System.EventArgs) Handles buttonRunExceptionCode_Click.Click

 Const TESTNUMBERAs Integer = 1

 'Получить количество итераций Dim numberItterationsAs

 Integer numberItterations = _

  CInt(textBoxNumberAttempts.Text)

 'Отобразить количество итераций, которые надлежит выполнить

 ListBox1.Items.Add("=>" + numberItterations.ToString() + " итераций")

 Dim count_SumLessThanZero As Integer

 Dim dataOut As Integer

 '–

 'Запустить таймер

 '–

 PerformanceSampling.StartSample(TEST_NUMBER, "Перехват исключения")

 '–

 'Выполнить цикл, в котором осуществляется вызов функции

 '–

 count_SumLessThanZero = 0

 Dim sumGreaterThanZero As Boolean

 Dim i As Integer

 While (i < numberItterations)

  Try

   '=========================

   'Вызвать тестовую функцию!

   '=========================

   sumGreaterThanZero = _

    exceptionIfLessThanZero_Add2Numbers(-2, -3, dataOut)

  Catch

   count_SumLessThanZero = count_SumLessThanZero + 1

  End Try

  i = i + 1

 End While 'конец цикла

 '–

 'Остановить таймер

 '–

 PerformanceSampling.StopSample(TEST_NUMBER)

 '–

 'Показать результаты пользователю

 '–

 If (count_SumLessThanZero = numberItterations) Then

  MsgBox("Тест выполнен")

  ListBox1.Items.Add( _

   PerformanceSampling.GetSampleDurationText(TEST_NUMBER))

 Else

  MsgBox("При выполнении теста возникали осложнения")

 End If

End Sub

Примеры к главе 8 (производительность и память)
Листинг 8.1. Применение отложенной загрузки, кэширования и освобождения графических ресурсов

Option Strict On

Public Class GraphicsGlobals

Private Shared s_Player_Bitmap1 As System.Drawing.Bitmap

Private Shared s_Player_Bitmap2 As System.Drawing.Bitmap

Private Shared s_Player_Bitmap3 As System.Drawing.Bitmap

Private Shared s_Player_Bitmap4 As System.Drawing.Bitmap

Private Shared s_colPlayerBitmaps As _

 System.Collections.ArrayList

'–

'Освободить все ресурсы

'–

Public Shared Sub g_PlayerBitmapsCollection_CleanUp()

 'Если не загружено ни одно изображение, то и память освобождать не от чего

 If (s_colPlayerBitmapsIs Nothing) Then Return

 'Дать указание каждому из этих объектов освободить

 'любые удерживаемые ими неуправляемые ресурсы

 s_Player_Bitmap1.Dispose()

 s_Player_Bitmap2.Dispose()

 s_Player_Bitmap3.Dispose()

 s_Player_Bitmap4.Dispose()

 'Обнулить каждую из этих переменных, чтобы им не соответствовали

 'никакие объекты в памяти

 s_Player_Bitmap1 = Nothing

 s_Player_Bitmap2 = Nothing

 s_Player_Bitmap3 = Nothing

 s_Player_Bitmap4 = Nothing

 'Избавиться от массива

 s_colPlayerBitmaps = Nothing

End Sub

'–

'Функция: возвращает коллекцию изображений

'–

Public Shared Function g_PlayerBitmapsCollection() _

 As System.Collections.ArrayList

 '–

 'Если изображения уже загружены, их достаточно только возвратить

 '–

 If Not (s_colPlayerBitmaps Is Nothing) Then

  Return scolPlayerBitmaps

 End If

 'Загрузить изображения как ресурсы из исполняемого двоичного файла

 Dim thisAssemblyAs System.Reflection.Assembly = _

  System.Reflection.Assembly.GetExecutingAssembly()

 Dim thisAssemblyNameAs System.Reflection.AssemblyName = _

  thisAssembly.GetName()

 Dim assemblyNameAs String = thisAssemblyName.Name

 'Загрузить изображения

 s_Player_Bitmap1 =New System.Drawing.Bitmap( _

  thisAssembly.GetManifestResourceStream(assemblyName _

  + ".Hank_RightRun1.bmp"))

 s_Player_Bitmap2 = New System.Drawing.Bitmap( _

  thisAssembly.GetManifestResourceStream(assemblyName _

  + ".Hank_RightRun2.bmp"))

 s_Player_Bitmap3 = New System.Drawing.Bitmap( _

  thisAssembly.GetManifestResourceStream(assemblyName _

  + ".Hank_LeftRun1.bmp"))

 s_Player_Bitmap4 = New System.Drawing.Bitmap( _

  thisAssembly.GetManifestResourceStream(assemblyName _

  + ".Hank_LeftRun2.bmp"))

 'Добавить изображения в коллекцию

 s_colPlayerBitmaps = New System.Collections.ArrayList

 s_colPlayerBitmaps.Add(s_Player_Bitmap1)

 s_colPlayerBitmaps.Add(s_Player_Bitmap2)

 s_colPlayerBitmaps.Add(s_Player_Bitmap3)

 s_colPlayerBitmaps.Add(s_Player_Bitmap4)

 'Возвратить коллекцию

 Return s_colPlayerBitmaps

End Function

Private Shared s_blackPen As System.Drawing.Pen

Private Shared s_whitePen As System.Drawing.Pen

Private Shared s_ImageAttribute As _

 System.Drawing.Imaging.ImageAttributes

Private Shared s_boldFont As System.Drawing.Font

'–

'Вызывается для освобождения от любых графических

'ресурсов, которые могли быть кэшированы

'–

Private Shared Sub g_CleanUpDrawingResources()

 'Освободить память от черного пера, если таковое имеется

 If Not (s_blackPenIs Nothing) Then

  s_blackPen.Dispose()

  s_blackPen = Nothing

 End If

 'Освободить память от белого пера, если таковое имеется

 If Not (s_whitePenIs Nothing) Then

  s_whitePen.Dispose()

  s_whitePen = Nothing

 End If

 'Освободить память от атрибута ImageAttribute, если таковой имеется.

 'Примечание. Метод Dispose() для этого типа не предусмотрен,

 'поскольку все его данные являются управляемыми

 If Not (s_ImageAttribute Is Nothing) Then

  s_ImageAttribute = Nothing

 End If

 'Освободить память от полужирного шрифта, если таковой имеется

 If Not (s_boldFontIs Nothing) Then

  b_boldFont.Dispose()

  s_boldFont = Nothing

 End If

End Sub

'–

'Эта функция позволяет получить доступ

'к черному перу, находящемуся в кэш-памяти

'–

Private Shared Function g_GetBlackPen() As System.Drawing.Pen

 'Если перо еще не существует, создать его

 If (s_blackPen Is Nothing) Then

  s_blackPen = New System.Drawing.Pen( _

   System.Drawing.Color.Black)

 End If

 'Возвратить черное перо

 Return s_blackPen

End Function

'–

'Эта функция позволяет получить доступ

'к белому перу, находящемуся в кэш-памяти

'–

Private Shared Function g_GetWhitePen() As System.Drawing.Pen

 'Если перо еще не существует, создать его

 If (s_whitePen Is Nothing) Then

  s_whitePen = New System.Drawing.Pen( _

   System.Drawing.Color.White)

 End If

 'Возвратить белое перо

 Return s_whitePen

End Function

'–

'Эта функция позволяет получить доступ

'к полужирному шрифту, находящемуся в кэш-памяти

'–

Private Shared Function g_GetBoldFont() As System.Drawing.Font

 'Если перо еще не существует, создать его

 If (s_boldFont Is Nothing) Then

  s_boldFont = New System.Drawing.Font( _

  System.Drawing.FontFamily.GenericSerif, 10, System.Drawing.FontStyle.Bold)

 End If

 'Возвратить полужирный шрифт

 Return s_boldFont

End Function

'–

'Эта функция позволяет осуществлять доступ

'к находящемуся в кэш-памяти объекту imageAttributes,

'который мы используем для изображений с прозрачностью

'–

Private Shared Function g_GetTransparencyImageAttribute() As _

 System.Drawing.Imaging.ImageAttributes

 'Если объект не существует, создать его

 If (s_ImageAttributeIs Nothing) Then

  'Создать атрибут изображения

  s_ImageAttribute = _

   New System.Drawing.Imaging.ImageAttributes

  s_ImageAttribute.SetColorKey(System.Drawing.Color.White, _

   System.Drawing.Color.White)

 End If

 'Возвратить его

 Return s_ImageAttribute

End Function

End Class

Листинг 8.2. Общий код, используемый во всех приведенных ниже вариантах тестов

'Желаемое число повторений теста

Const LOOP_SIZE As Integer = 8000

'–

'Эта функция переустанавливает содержимое нашего тестового

'массива, что обеспечивает возможность многократного

'выполнения тестового алгоритма

'–

Private Sub ResetTestArray(ByRef testArray() As String)

 If (testArray Is Nothing) Then

  ReDim testArray(6)

 End If

 testArray(0) = "big_blue_duck"

 testArray(1) = "small_yellow_horse"

 testArray(2) = "wide_blue_cow"

 testArray(3) = "tall_green_zepplin"

 testArray(4) = "short_blue_train"

 testArray(5) = "short_purple_dinosaur"

End Sub

Листинг 8.3. Тестовый пример, демонстрирующий неэкономное распределение памяти (типичный первоначальный вариант реализации интересующей нас функции)

Private Sub Button2_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button2.Click

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

 'тест начнется с чистого состояния.

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

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

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

 System.GC.Collect()

 Dim testArray() As String = Nothing

 '–

 'Просмотреть элементы массива и

 'найти те из них, в которых средним словом является

 '"blue". Заменить "blue" на "orange"

 'Запустить секундомер для нашего теста!

 '–

 PerformanceSampling.StartSample(0, "WastefulWorkerClass")

 Dim workerClass1 As WastefulWorkerClass

 Dim outerLoop As Integer

 For outerLoop = 1 To LOOP_SIZE

  'Присвоить элементам массива значения, которые мы хотим использовать

  'при тестировании

  ResetTestArray(testArray)

  Dim topIndex = testArray.Length – 1

  Dim idx As Integer

  For idx = 0 To topIndex

   '–

   'Создать экземпляр вспомогательного класса,

   'который расчленяет строку на три части

   'Это неэкономный способ!

   '–

   workerClass1 = New WastefulWorkerClass(testArray(idx))

   'Если средним словом является "blue", заменить его на "orange"

   If (workerClass1.MiddleSegment = "blue") Then

    'Заменить средний сегмент

    workerClass1.MiddleSegment = "orange"

    'Заменить слово

    testArray(idx) = workerClass1.getWholeString()

   End If

  Next 'внутренний цикл

 Next 'внешний цикл

 'Получить время окончания теста

 PerformanceSampling.StopSample(0)

 MsgBox(PerformanceSampling.GetSampleDurationText(0))

End Sub

Листинг 8.4. Рабочий класс для первого тестового примера

Option Strict On

Imports System

Public Class WastefulWorkerClass

Private m_beginning_segment As String

Public Property BeginSegment() As String

 Get

  Return m_beginning_segment

 End Get

 Set(ByVal Value As String)

  m_beginning_segment = Value

 End Set

End Property

Private m_middle_segment As String

Public Property MiddleSegment() As String

 Get

  Return m_middle_segment

 End Get

 Set(ByVal Value As String)

  m_middle_segment = Value

 End Set

End Property

Private m_end_segment As String

Public Property EndSegment() As String

 Get

  Return m_end_segment

 End Get

 Set(ByVal Value As String)

  m_end_segment = Value

 End Set

End Property

Public Sub New(ByVal in_word As String)

 Dim index_segment1 As Integer

 'Осуществляем поиск символов подчеркивания ("_") в строке

 index_segment1 = in_word.IndexOf("_", 0)

 'В случае отсутствия символов "_" все, что нам нужно, это первый сегмент

 If (index_segment1 = -1) Then

  m_beginning_segment = in_word

  m_middle_segment = ""

  m_end segment = ""

  Return

 Else

  'Если присутствует символ "_", отсечь его

  'Если первым символом является "_", то первым сегментом будет ""

  If (index_segment1 = 0) Then

   m_beginning_segment = ""

  Else

   'Первый сегмент

   m_beginning_segment = in_word.Substring(0, index_segment1)

  End If

  'Найти второй символ "_"

  Dim index_segment2 As Integer

  index_segment2 = in_word.IndexOf("_", index_segment1 + 1)

  'Второй символ "_" отсутствует

  If (index_segment2 = -1) Then

   m_middle_segment = ""

   m_end_segment = in_word.Substring(index_segment1 + 1)

   Return

  End If

  'Установить последний сегмент

  m_middle_segment = in_word.Substring(index_segment1 + 1, _

   index_segment2 – index_segment1 – 1)

  m_end_segment = in_word.Substring(index_segment2 + 1)

 End If

End Sub

'Возвращает все три сегмента, объединенные символами "_"

Public Function getWholeString() As String

 Return m_beginning_segment + "_" + m_middle_segment + "_" + _

  m_end_segment

End Function

End Class

Листинг 8.5. Тестовый пример, демонстрирующий уменьшение объема памяти, распределяемой для объектов (типичный образец улучшения первоначального варианта реализации интересующей нас функции)

Private Sub Button3_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button3.Click

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

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

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

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

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

 System.GC.Collect()

 Dim testArray() As String = Nothing

 '–

 'Просмотреть элементы массива и

 'найти те из них, в которых средним словом является

 '"blue". Заменить "blue" на "orange"

 'Запустить секундомер!

 '–

 PerformanceSampling.StartSample(1, "LessWasteful")

 '–

 'БОЛЕЕ ЭКОНОМНЫЙ СПОСОБ: Распределить память для объекта

 'до вхождения в цикл

 '–

 Dim workerClass1 As LessWastefulWorkerClass

 workerClass1 = New LessWastefulWorkerClass

 Dim outerLoop As Integer

 For outerLoop = 1 To LOOP_SIZE

  'Присвоить элементам массива значения, которые мы хотим использовать

  'при тестировании ResetTestArray(testArray)

  Dim topIndex As Integer = testArray.Length -1 Dim idx As Integer

  For idx = 0 To topIndex

   '–

   'Теперь вместо повторного распределения памяти для объекта

   'нам достаточно лишь повторно воспользоваться им

   '–

   'workerClass1 = new WastefulWorkerClass(

   ' testArray(topIndex))

   workerClass1.ReuseClass(testArray(idx))

   'Если средним словом является "blue", заменить его на "orange"

   If (workerClass1.MiddleSegment = "blue") Then

    'Заменить средний сегмент

    workerClass1.MiddleSegment = "orange"

    'Заменить слово

    testArray(idx) = workerClass1.getWholeString()

   End If

  Next ' внутренний цикл

 Next 'внешний цикл

 'Остановить секундомер!

 PerformanceSampling.StopSample(1)

 MsgBox(PerformanceSampling.GetSampleDurationText(1))

End Sub

Листинг 8.6. Рабочий класс для второго тестового примера

Option Strict

On Imports System

Public Class LessWastefulWorkerClass

Private m_beginning_segment As String

Public Property BeginSegment() As String

 Get

  Return m_beginning_segment

 End Get

 Set(ByVal Value As String)

  m_beginning_segment = Value

 End Set

End Property

Private m_middle_segment As String

Public Property MiddleSegment() As String

 Get

  Return m_middle_segment

 End Get

 Set(ByVal Value As String)

  m_middle_segment = Value

 End Set

End Property

Private m_end_segment As String

Public Property EndSegment() As String

 Get

  Return m_end_segment

 End Get

 Set(ByVal Value As String)

  m_end_segment = Value

 End Set

End Property

Public Sub ReuseClass(ByVal in_word As String)

 '–

 'Для повторного использования класса необходимо

 'полностью очистить внутреннее состояние

 '–

 m_beginning_segment = ""

 m_middle_segment = ""

 m_end_segment = ""

 Dim index_segment1 As Integer

 'Осуществляем поиск символов подчеркивания ("_") в строке

 index_segment1 = in_word.IndexOf("_", 0)

 'В случае отсутствия символов "_" все, что нам нужно, это первый сегмент

 If (index_segment1 = -1) Then

  m_beginning_segment = in_word

  Return

 Else

  'Если присутствует символ "_", отсечь его

  If (index_segment1 = 0) Then

  Else

   m_beginning_segment = in_word.Substring(0, _

    index_segment1)

  End If

  Dim index_segment2 As Integer

  index_segment2 = in_word.IndexOf("_", index_segment1 + 1)

  If (index segment2 = -1) Then

   m_end_segment = in_word.Substring(index_segment1 + 1)

   Return

  End If

  'Установить последний сегмент

  m_middle_segment = in_word.Substring(index_segment1 + 1, _

   index_segment2 – index_segment1 – 1)

  m_end_segment = in_word.Substring(index_segment2 + 1)

 End If

End Sub

Public Function getWholeString() As String

 Return m_beginning_segment + " " + m_middle_segment + " " + _

  m_end_segment

End Function

End Class

Листинг 8.7. Тестовый пример, демонстрирующий значительное уменьшение объема памяти, распределяемой для объектов (типичный образец существенной алгоритмической оптимизации первоначального варианта реализации интересующей нас функции)

Private Sub Button5 Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button5.Click

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

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

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

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

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

 System.GC.Collect()

 Dim testArray() As String = Nothing

 '–

 'Просмотреть элементы массива и

 'найти те из них, в которых средним словом является

 '"blue". Заменить "blue" на "orange"

 '–

 'Запустить секундомер перед началом выполнения теста

 PerformanceSampling.StartSample(2, "DefferedObjects")

 '–

 'БОЛЕЕ ЭКОНОМНЫЙ СПОСОБ: Распределить память для объекта

 'до вхождения в цикл

 '–

 Dim workerClass1 As LessAllocationsWorkerClass

 workerClass1 = New LessAllocationsWorkerClass

 Dim outerLoop As Integer

 For outerLoop = 1 To LOOP_SIZE

  'Присвоить элементам массива значения, которые мы хотим использовать

  'при тестировании

  ResetTestArray(testArray)

  Dim topIndex As Integer = testArray.Length – 1 Dim idx As Integer

  For idx = 0 To topIndex

   '–

   'Более экономный способ:

   'Теперь вместо повторного распределения памяти для объекта

   'нам достаточно лишь повторно воспользоваться им

   'Кроме того: в этом варианте реализации дополнительные строки

   'НЕ создаются

   'workerClass1 = new WastefulWorkerClass(

   '      testArray[topIndex])

   '–

   workerClass1.ReuseClass(testArray(idx))

   'Если средним словом является "blue", заменить его на "orange"

   '–

   'Более экономный способ:

   'При таком способе сравнения не требуется создавать

   'никаких дополнительных строк

   '–

   If (workerClass1.CompareMiddleSegment("blue") = 0) Then

    'Заменить средний сегмент

    workerClass1.MiddleSegment = "orange"

    'Заменить слово

    testArray(idx) = workerClass1.getWholeString()

   End If

  Next 'внутренний цикл

 Next 'внешний цикл

 'Остановить секундомер!

 PerformanceSampling.StopSample(2)

 MsgBox(PerformanceSampling.GetSampleDurationText(2))

End Sub

Листинг 8.8. Рабочий класс для третьего тестового примера

Option Strict On

Imports System

Public Class LessAllocationsWorkerClass

Public WriteOnly Property MiddleSegment() As String

 Set(ByVal Value As String)

  m_middleSegmentNew = Value

 End Set

End Property

Private m_middleSegmentNew As String

Private m_index_1st_undscore As Integer

Private m_index_2nd_undscore As Integer

Private m_stringIn As String

Public Sub ReuseClass(ByVal in_word As String)

 '–

 'Для повторного использования класса необходимо

 'полностью очистить внутреннее состояние

 '–

 m_index_1st_undscore = -1

 m_index_2nd_undscore = -1

 m_middleSegmentNew = Nothing

 m_stringIn = in_word 'Это не приводит к созданию копии строки

 'Осуществляем поиск символов подчеркивания ("_") в строке

 m_index_1st_undscore = in_word.IndexOf("_", 0)

 'В случае отсутствия символов "_" все, что нам нужно, это первый сегмент

 If (m_index_1st_undscore = -1) Then

  Return

 End If

 'Найти второй символ "_"

 m_index_2nd_undscore = in_word.IndexOf("_", _

  m_index_1st_undscore + 1)

End Sub

Public Function CompareMiddleSegment(ByVal compareTo As String) As Integer

 'В случае отсутствия второго символа "_" отсутствует и средний сегмент

 If (m_index_2nd_undscore < 0) Then

  'Если мы сравниваем с пустой строкой, то это означает

  'совпадение

  If ((compareTo = Nothing) OrElse (compareTo = "")) Then

   Return 0

  End If

  Return -1

 End If

 'Сравнить средний сегмент с первым и вторым сегментами

 Return System.String.Compare(m_stringIn, m_index_1st_undscore + 1, _

  compareTo, 0, _

  m_index_2nd_undscore – m_index_1st_undscore – 1)

End Function

Public Function getWholeString() As String

 'Если полученный средний сегмент не является новым,

 'возвратить исходный сегмент

 If (m_middleSegmentNew = Nothing) Then

  Return m_stringIn

 End If

 'Создать возвращаемую строку

 Return m_stringIn.Substring(0, m index_1st_undscore + 1) + _

  m_middleSegmentNew + m_stringIn.Substring( _

  m_index_2nd_undscore, _

  m_stringIn.Length – m_index_2nd_undscore)

End Function

End Class

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

Const COUNT_UNTIL As Integer = 300

Const LOOP_ITERATIONS As Integer = 40

'–

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

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

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

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

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

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

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

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

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

 System.GC.Collect()

 Dim numberToStore As Integer

 PerformanceSampling.StartSample(0, "StringAllocaitons")

 Dim total_result As String

 Dim outer_loop As Integer

 For outer_loop = 1 To LOOP_ITERATIONS

  'Сбросить старый результат


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

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