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
'Сбросить старый результат
total_result = ""
'Выполнять цикл до максимального значения x_counter, каждый раз
'присоединяя очередную тестовую строку к рабочей строке
Dim x_counter As Integer
For x_counter = 1 To COUNT_UNTIL
total_result = total_result + numberToStore.ToString() + ", "
'Увеличить значение счетчика
numberToStore = numberToStore + 1
Next
Next
PerformanceSampling.StopSample(0)
'Отобразить длину строки
MsgBox("String Length: " + total_result.Length.ToString())
'Отобразить строку
MsgBox("String : " + total_result)
'Отобразить длительность интервала времени, ушедшего на вычисления