Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources] - نسخه متنی

Ivo Salmre

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید











Chapter 8 (Performance and Memory) Samples

Listing 8.1. Ways of Deferred Loading, Caching, and Releasing Graphics Resources



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
'---------------------------------------------------
'Releases all the resoruces
'---------------------------------------------------
Public Shared Sub g_PlayerBitmapsCollection_CleanUp()
'If we don't have any bitmaps loaded, there is nothing
'to clean up
If (s_colPlayerBitmaps Is Nothing) Then Return
'Tell each of these objects to free up
'whatever nonmanaged resources they are
'holding.
s_Player_Bitmap1.Dispose()
s_Player_Bitmap2.Dispose()
s_Player_Bitmap3.Dispose()
s_Player_Bitmap4.Dispose()
'Clear each of these variables, so they do not keep
'the objects in memory
s_Player_Bitmap1 = Nothing
s_Player_Bitmap2 = Nothing
s_Player_Bitmap3 = Nothing
s_Player_Bitmap4 = Nothing
'Get rid of the array list
s_colPlayerBitmaps = Nothing
End Sub
'---------------------------------------------------
'Function: Returns Collection of Bitmaps
'---------------------------------------------------
Public Shared Function g_PlayerBitmapsCollection() _
As System.Collections.ArrayList
'---------------------------------------------------
'If we have already loaded these, just return them
'---------------------------------------------------
If Not (s_colPlayerBitmaps Is Nothing) Then
Return s_colPlayerBitmaps
End If
'Load the bitmaps as resources from our executuable binary
Dim thisAssembly As System.Reflection.Assembly = _
System.Reflection.Assembly.GetExecutingAssembly()
Dim thisAssemblyName As System.Reflection.AssemblyName = _
thisAssembly.GetName()
Dim assemblyName As String = thisAssemblyName.Name
'Load the bitmaps
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"))
'Add them to the collection
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 the collection
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
'---------------------------------------
'Called to release any drawing resources we
'may have cached
'---------------------------------------
Private Shared Sub g_CleanUpDrawingResources()
'Clean up the black pen, if we've got one
If Not (s_blackPen Is Nothing) Then
s_blackPen.Dispose()
s_blackPen = Nothing
End If
'Clean up the white pen, if we've got one
If Not (s_whitePen Is Nothing) Then
s_whitePen.Dispose()
s_whitePen = Nothing
End If
'Clean up the ImageAttribute, if we've got one
'Note: This type does not have a Dispose() method
'because all of its data is managed data
If Not (s_ImageAttribute Is Nothing) Then
s_ImageAttribute = Nothing
End If
'Clean up the bold font, if we've got one
If Not (s_boldFont Is Nothing) Then
s_boldFont.Dispose()
s_boldFont = Nothing
End If
End Sub
'-------------------------------------
'This function enables us to access the
'cached black pen
'-------------------------------------
Private Shared Function g_GetBlackPen() As System.Drawing.Pen
'If the pen does not exist yet, create it
If (s_blackPen Is Nothing) Then
s_blackPen = New System.Drawing.Pen( _
System.Drawing.Color.Black)
End If
'Return the black pen
Return s_blackPen
End Function
'-------------------------------------
'This function enables us to access the
'cached white pen
'-------------------------------------
Private Shared Function g_GetWhitePen() As System.Drawing.Pen
'If the pen does not exist yet, create it
If (s_whitePen Is Nothing) Then
s_whitePen = New System.Drawing.Pen( _
System.Drawing.Color.White)
End If
'Return the white pen
Return s_whitePen
End Function
'-------------------------------------
'This function enables us to access the
'cached bold font
'-------------------------------------
Private Shared Function g_GetBoldFont() As System.Drawing.Font
'If the pen does not exist yet, create it
If (s_boldFont Is Nothing) Then
s_boldFont = New System.Drawing.Font( _
System.Drawing.FontFamily.GenericSerif, _
10, System.Drawing.FontStyle.Bold)
End If
'Return the bold font
Return s_boldFont
End Function
'-----------------------------------------------
'This function enables us to access the
'cached imageAttributes we use for bitmaps
'with transparency
'-----------------------------------------------
Private Shared Function g_GetTransparencyImageAttribute() As _
System.Drawing.Imaging.ImageAttributes
'If it does not exist, create it
If (s_ImageAttribute Is Nothing) Then
'Create an image attribute
s_ImageAttribute = _
New System.Drawing.Imaging.ImageAttributes
s_ImageAttribute.SetColorKey(System.Drawing.Color.White, _
System.Drawing.Color.White)
End If
'Return it
Return s_ImageAttribute
End Function
End Class

Listing 8.2. Common Code Used in All Test Cases Below



'Number of times we want to repeat the test
Const LOOP_SIZE As Integer = 8000
'----------------------------------------------------
'This function resets the contents of our test
'array, so we can run the test algorithm
'over and over
'----------------------------------------------------
Private Sub ResetTestArray(ByRef testArray() As String)
If (testArray Is Nothing) Then
ReDim testArray(5)
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

Listing 8.3. A Test Case Showing Wasteful Allocations (a Typical First Implementation of a Function)



Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
'Run the garbage collector so we know we're starting
'from a clean slate for our test.
'ONLY CALL DURING TESTING! Calling the GC manually will
'slow(down)
'overall application throughput!
System.GC.Collect()
Dim testArray() As String = Nothing
'---------------------------------------------
'Go through the items in the array and
'look for ones where the middle word is
'"blue". Replace the "blue" with "orange"
'---------------------------------------------
'Start the stopwatch for our test!
PerformanceSampling.StartSample(0, "WastefulWorkerClass")
Dim workerClass1 As WastefulWorkerClass
Dim outerLoop As Integer
For outerLoop = 1 To LOOP_SIZE
'Set up the data in the array we want to do our test on
ResetTestArray(testArray)
Dim topIndex = testArray.Length - 1
Dim idx As Integer
For idx = 0 To topIndex
'------------------------------------
'Create an instance of a helper class
'that dissects our string into 3 pieces
'
'This is wasteful!
'------------------------------------
workerClass1 = New WastefulWorkerClass(testArray(idx))
'If the middle word is "blue", make it "orange"
If (workerClass1.MiddleSegment = "blue") Then
'Replace the middle item
workerClass1.MiddleSegment = "orange"
'Replace the word
testArray(idx) = workerClass1.getWholeString()
End If
Next 'inner loop
Next 'outer loop
'Get the time we completed our test
PerformanceSampling.StopSample(0)
MsgBox(PerformanceSampling.GetSampleDurationText(0))
End Sub

Listing 8.4. The Worker Class for our First Test Case



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
'Look for a "_" in the string
index_segment1 = in_word.IndexOf("_", 0)
'If there is no "_", the first segment is the whole thing
If (index_segment1 = -1) Then
m_beginning_segment = in_word
m_middle_segment = "
m_end_segment = "
Return
Else 'If there is a "_", split it
'If the "_" is the first char, the 1st segment is "
If (index_segment1 = 0) Then
m_beginning_segment = "
Else
'The first segment
m_beginning_segment = in_word.Substring(0, index_segment1)
End If
'Find the second "_"
Dim index_segment2 As Integer
index_segment2 = in_word.IndexOf("_", index_segment1 + 1)
'Second "_" does not exist
If (index_segment2 = -1) Then
m_middle_segment = "
m_end_segment = in_word.Substring(index_segment1 + 1)
Return
End If
'Set the end segment
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
'Returns the whole 3 segments joined by "-"s
Public Function getWholeString() As String
Return m_beginning_segment + "_" + m_middle_segment + "_" + _
m_end_segment
End Function
End Class

Listing 8.5. A Test Case Showing Slightly Reduced Object Allocations (a Typical Refinement of a First Function Implementation)



Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
'Run the garbage collector so we start from a "clean"
'state for our test
'ONLY CALL DURING TESTING! Calling the GC manually will slow
'down overall application throughput!
System.GC.Collect()
Dim testArray() As String = Nothing
'---------------------------------------------
'Go through the items in the array and
'look for ones where the middle word is
'"blue". Replace the "blue" with "orange"
'---------------------------------------------
'Start the stopwatch!
PerformanceSampling.StartSample(1, "LessWasteful")
'------------------------------------------------
'LESS WASTEFUL: Allocate the object before we get in the
'loop
'------------------------------------------------
Dim workerClass1 As LessWastefulWorkerClass
workerClass1 = New LessWastefulWorkerClass
Dim outerLoop As Integer
For outerLoop = 1 To LOOP_SIZE
'Set up the data in the array we want to do our test on
ResetTestArray(testArray)
Dim topIndex As Integer = testArray.Length - 1
Dim idx As Integer
For idx = 0 To topIndex
'----------------------------------------------------
'Instead of reallocating the object, let's just reuse
'it
'----------------------------------------------------
'workerClass1 = new WastefulWorkerClass(
' testArray(topIndex))
workerClass1.ReuseClass(testArray(idx))
'If the middle word is "blue", make it "orange"
If (workerClass1.MiddleSegment = "blue") Then
'Replace the middle item
workerClass1.MiddleSegment = "orange"
'Replace the word
testArray(idx) = workerClass1.getWholeString()
End If
Next 'inner loop
Next 'outer loop
'Stop the stopwatch!
PerformanceSampling.StopSample(1)
MsgBox(PerformanceSampling.GetSampleDurationText(1))
End Sub

Listing 8.6. The Worker Class for Our Second Test Case



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)
'-----------------------------------------
'To reuse the class, clear all the internal state
'-----------------------------------------
m_beginning_segment = "
m_middle_segment = "
m_end_segment = "
Dim index_segment1 As Integer
'Look for a "_" in the string
index_segment1 = in_word.IndexOf("_", 0)
'If there is no "_", the first segment is the whole thing
If (index_segment1 = -1) Then
m_beginning_segment = in_word
Return
Else 'If there is a "_", split it
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
'Set the end segment
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

Listing 8.7. A Test Case Showing Significantly Reduced Object Allocations (Typical of Doing Significant Algorithm Optimizations on the First Implementation)



Private Sub Button5_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button5.Click
'Run the garbage collector, so we start from a
'clean slate for our test
'ONLY CALL DURING TESTING! Calling the GC manually will slow
'down overall application throughput!
System.GC.Collect()
Dim testArray() As String = Nothing
'---------------------------------------------
'Go through the items in the array and
'look for ones where the middle word is
'"blue". Replace the "blue" with "orange"
'---------------------------------------------
'Start the stopwatch for the test
PerformanceSampling.StartSample(2, "DeferredObjects")
'------------------------------------------------
'Less wasteful: Allocate the object before we get in the
'loop
'------------------------------------------------
Dim workerClass1 As LessAllocationsWorkerClass
workerClass1 = New LessAllocationsWorkerClass
Dim outerLoop As Integer
For outerLoop = 1 To LOOP_SIZE
'Set up the data in the array we want to do our test on
ResetTestArray(testArray)
Dim topIndex As Integer = testArray.Length - 1
Dim idx As Integer
For idx = 0 To topIndex
'------------------------------------------------------
'Less wasteful:
'Instead of reallocating the object, let's just reuse it
'Also: The implementation does NOT create additional
'strings
'------------------------------------------------------
'workerClass1 = new WastefulWorkerClass(
' testArray[topIndex])
workerClass1.ReuseClass(testArray(idx))
'If the middle word is "blue", make it "orange"
'--------------------------------------------------
'Less wasteful:
'This compare does not need to create any additional
'strings
'--------------------------------------------------
If (workerClass1.CompareMiddleSegment("blue") = 0) Then
'Replace the middle item
workerClass1.MiddleSegment = "orange"
'Replace the word
testArray(idx) = workerClass1.getWholeString()
End If
Next 'inner loop
Next 'outer loop
'Stop the stopwatch!
PerformanceSampling.StopSample(2)
MsgBox(PerformanceSampling.GetSampleDurationText(2))
End Sub

Listing 8.8. The Worker Class for Our Third Test Case



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)
'-----------------------------------------
'To reuse the class, clear all the internal state
'-----------------------------------------
m_index_1st_undscore = -1
m_index_2nd_undscore = -1
m_middleSegmentNew = Nothing
m_stringIn = in_word 'This does not make a string copy
'Look for a "_" in the string
m_index_1st_undscore = in_word.IndexOf("_", 0)
'If there is no "_", the first segment is the whole thing
If (m_index_1st_undscore = -1) Then
Return
End If
'Look for the second "_"
m_index_2nd_undscore = in_word.IndexOf("_", _
m_index_1st_undscore + 1)
End Sub
Public Function CompareMiddleSegment(ByVal compareTo As _
String) As Integer
'If there is no second underscore, there is no middle
If (m_index_2nd_undscore < 0) Then
'If we are comparing to an empty string, then this is a
'match
If ((compareTo = Nothing) OrElse (compareTo = ")) Then
Return 0
End If
Return -1
End If
'Compare the middle segment to the first and second segments
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 we've been given no new middle segment, return the
'original
If (m_middleSegmentNew = Nothing) Then
Return m_stringIn
End If
'Build the return string
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

Listing 8.9. Comparing String Usage to StringBuilder in Algorithms



Const COUNT_UNTIL As Integer = 300
Const LOOP_ITERATIONS As Integer = 40
'-------------------------------------------------------
'NOT VERY EFFICIENT!
'
'Use regular strings to simulate building a typical set of
'strings
'-------------------------------------------------------
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'Do a garbage collection before we start running, to start
'us from a clean state.
'ONLY CALL DURING TESTING! Calling the GC manually will slow
'down overall application throughput!
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
'Clear out the old result
total_result = "
'Count up to 'x_counter' and append the test of each count
'to our working string
Dim x_counter As Integer
For x_counter = 1 To COUNT_UNTIL
total_result = total_result + numberToStore.ToString() _
+ ", "
'Advance the counter
numberToStore = numberToStore + 1
Next
Next
PerformanceSampling.StopSample(0)
'Display the length of the string
MsgBox("String Length: " + total_result.Length.ToString())
'Display string
MsgBox("String : " + total_result)
'Display the time it tool to run
MsgBox(PerformanceSampling.GetSampleDurationText(0))
End Sub
'-------------------------------------------------------
'MUCH MORE EFFICIENT!
'
'Use the string builder to simulate building a fairly typical
'set of strings
'-------------------------------------------------------
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
'Do a garbage collection before we start running, to start
'us from a clean state.
'ONLY CALL DURING TESTING! Calling the GC manually will slow
'down overall application throughput!
System.GC.Collect()
Dim sb As System.Text.StringBuilder = _
New System.Text.StringBuilder
Dim total_result As String
Dim numberToStore As Integer
PerformanceSampling.StartSample(1, "StringBuilder")
Dim outer_loop As Integer
For outer_loop = 1 To LOOP_ITERATIONS
'Clear the string builder
sb.Length = 0
'Clear out our old result string
total_result = "
'Count up to 'x_counter' and append the test of each count
'to our working string
Dim x_counter As Integer
For x_counter = 1 To COUNT_UNTIL
sb.Append(numberToStore)
sb.Append(", ")
'Advance the counter
numberToStore = numberToStore + 1
Next
'Pretend we're doing something with the string...
total_result = sb.ToString()
Next
PerformanceSampling.StopSample(1)
'Display the length of the string
MsgBox("String Length: " + total_result.Length.ToString())
'Display string
MsgBox("String : " + total_result)
'Display the time it tool to run
MsgBox(PerformanceSampling.GetSampleDurationText(1))
End Sub


/ 159