Chapter 7 (Performance Introduction) Samples
Listing 7.1. Performance Sampling Code to Instrument Your Code With
Option Strict On Imports System Friend Class PerformanceSampling 'Arbitrary number, but 8 seems like enough samplers for 'most uses. 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 '---------------------------------------------------- 'Take a start tick count for a sample '---------------------------------------------------- Friend Shared Sub StartSample(ByVal sampleIndex As Integer, _ ByVal sampleName As String) m_perfSamplesNames(sampleIndex) = sampleName m_perfSamplesStartTicks(sampleIndex) = _ System.Environment.TickCount() End Sub '---------------------------------------------------- 'Take a start tick count for a sample '---------------------------------------------------- Friend Shared Sub StopSample(ByVal sampleIndex As Integer) Dim stopTickCount As Integer = System.Environment.TickCount 'The counter resets itself every 24.9 days '(which is about 2 billion ms) 'we'll account for this unlikely possibility If (stopTickCount >= m_perfSamplesStartTicks(sampleIndex)) _ Then 'In almost all cases we will run this code. m_perfSamplesDuration(sampleIndex) = _ stopTickCount - m_perfSamplesStartTicks(sampleIndex) Else 'We have wrapped back around to zero and should account 'for this m_perfSamplesDuration(sampleIndex) = stopTickCount + _ (Integer.MaxValue - m_perfSamplesStartTicks(sampleIndex)) + 1 End If End Sub '---------------------------------------------------- 'Return the length of a sample we have taken '(length in milliseconds) '---------------------------------------------------- Friend Shared Function GetSampleDuration(ByVal sampleIndex _ As Integer) As Integer Return m_perfSamplesDuration(sampleIndex) End Function 'Returns the number of seconds that have elapsed 'during the sample period Friend Shared Function GetSampleDurationText(ByVal _ sampleIndex As Integer) As String Return m_perfSamplesNames(sampleIndex) + ": " + _ System.Convert.ToString( _ (m_perfSamplesDuration(sampleIndex) / CDbl(1000.0)) _ ) + " seconds." End Function End Class
Listing 7.2. Test Code Showing Use of Timing Instrumentation Code Above
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Const TEST_SAMPE_INDEX As Integer = 2 'Choose any valid index 'Start sampling PerformanceSampling.StartSample(TEST_SAMPE_INDEX, _ "TestSample") 'Show the message box MsgBox("Hit OK to finish Sample") 'Stop sampling PerformanceSampling.StopSample(TEST_SAMPE_INDEX) 'Show the results MsgBox(PerformanceSampling.GetSampleDurationText( _ TEST_SAMPE_INDEX)) End Sub
Listing 7.3. Three Different Levels of User Responsiveness
'Place captions on the buttons Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Button1.Text = "Bad experience" Button2.Text = "Better experience" Button3.Text = "Even Better" End Sub '---------------------------------------- 'Example of a bad experience: ' - No visual indication is given when work is started ' - No visual indication is given when work is ended ' - User interface is unresponsive during work ' - End user is left to guess when the task completes '---------------------------------------- Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click 'Simulate work by pausing for 4 seconds System.Threading.Thread.Sleep(4000) End Sub '---------------------------------------- 'Example of a better experience: ' + A visual indication is given when work is started ' (Wait cursor appears) ' + A visual indication is given when work is ended ' (Wait cursor disappears) ' - User interface is unresponsive during work ' + End user knows when task is completed and UI is reponsive ' again '---------------------------------------- Private Sub Button2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button2.Click System.Windows.Forms.Cursor.Current = _ System.Windows.Forms.Cursors.WaitCursor 'Simulate work by pausing for 4 seconds System.Threading.Thread.Sleep(4000) System.Windows.Forms.Cursor.Current = _ System.Windows.Forms.Cursors.Default End Sub '---------------------------------------- 'Example of an even better experience: ' + A visual indication is given when work is started ' (Wait cursor appears) ' + Additional text is displayed telling the user what is ' going on ' + A visual indication is given when work is ended ' (Wait cursor disappears) ' - User interface is unresponsive during work ' + End user knows when task is completed and UI is ' responsive again ' + Text tells user what happened '---------------------------------------- Private Sub Button3_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button3.Click 'Give user text that explains what is going on Label1.Text = "Wait! Doing work!" 'Force the UI to update the text '(otherwise it will wait until it processes the repaint 'message, this may be after we exit this function) Label1.Update() 'Show wait cursor System.Windows.Forms.Cursor.Current = _ System.Windows.Forms.Cursors.WaitCursor 'Simulate work by pausing for 2.8 seconds System.Threading.Thread.Sleep(2800) 'Optional Incremental status update Label1.Text = "Wait! Almost done!" Label1.Update() 'Simulate work by pausing for 1.2 seconds System.Threading.Thread.Sleep(1200) 'Give text indication that we are done '(Update whenever UI normally updates) Label1.Text = "Success!" 'Get rid of the wait cursor System.Windows.Forms.Cursor.Current = _ System.Windows.Forms.Cursors.Default End Sub
Listing 7.4. Performance Comparison Between Exception-Throwing Algorithm and Non-Exception-Throwing Algorithm
'=========================================================== 'Note: This sample uses the "PerformanceSampling" class ' defined earlier in this chapter. Make sure this ' class is included in your project. '=========================================================== 'TEST FUNCTION: ' 'Attempt to add 'n1' and 'n2' together and return the result ' in 'n3' ' ' return: ' TRUE: If the result is positive ' FALSE: If the result is negative '=========================================================== Function returnFalseIfLessThanZero_Add2Numbers( _ ByVal n1 As Integer, ByVal n2 As Integer, _ ByRef n3 As Integer) As Boolean n3 = n1 + n2 'Is the item less than 0? If (n3 < 0) Then Return False End If Return True End Function '=========================================================== 'TEST FUNCTION: ' 'Attempt to add 'n1' and 'n2' together and return the result ' in 'n3' ' 'This function THROWS AN EXCEPTION if 'n3' is less than 0. 'Otherwise TRUE is returned '=========================================================== Function exceptionIfLessThanZero_Add2Numbers( _ ByVal n1 As Integer, ByVal n2 As Integer, _ ByRef n3 As Integer) As Boolean n3 = n1 + n2 'Is the item less than 0? If (n3 < 0) Then Throw New Exception("Less than 0!") End If Return True End Function '=========================================================== 'Calls a simple function a large number of times and 'measures the total execution time. ' 'The function called DOES NOT raise an exception '=========================================================== Private Sub buttonRunNoExceptionCode_Click(ByVal sender As _ System.Object, ByVal e As System.EventArgs) Handles _ buttonRunNoExceptionCode.Click Const TEST_NUMBER As Integer = 0 Dim numberItterations As Integer numberItterations = _ CInt(textBoxNumberAttempts.Text) 'Show the number of iterations we are going to perform ListBox1.Items.Add("=>" + numberItterations.ToString() + _ " Iterations") Dim count_SumLessThanZero As Integer Dim dataOut As Integer '----------------------------------------------------------- 'Start the performance timer '----------------------------------------------------------- PerformanceSampling.StartSample(TEST_NUMBER, "No Exception") '----------------------------------------------------------- 'Run the loop that calls the function '----------------------------------------------------------- count_SumLessThanZero = 0 Dim sumGreaterThanZero As Boolean Dim i As Integer While (i < numberItterations) '======================= 'Call the test function! '======================= sumGreaterThanZero = _ returnFalseIfLessThanZero_Add2Numbers(-2, -3, dataOut) If (sumGreaterThanZero = False) Then count_SumLessThanZero = count_SumLessThanZero + 1 End If i = i + 1 End While '----------------------------------------------------------- 'Stop the performance timer '----------------------------------------------------------- PerformanceSampling.StopSample(TEST_NUMBER) '----------------------------------------------------------- 'Output the results to the user '----------------------------------------------------------- If (count_SumLessThanZero = numberItterations) Then MsgBox("Test Passed") ListBox1.Items.Add( _ PerformanceSampling.GetSampleDurationText(TEST_NUMBER)) Else MsgBox("Something is wrong with the test") End If End Sub '=========================================================== 'Calls a simple function a large number of times and 'measures the total execution time. ' 'The function called DOES raise an exception '=========================================================== Private Sub buttonRunExceptionCode_Click(ByVal sender As _ System.Object, ByVal e As System.EventArgs) Handles _ buttonRunExceptionCode.Click Const TEST_NUMBER As Integer = 1 'Get the number of iterations Dim numberItterations As Integer numberItterations = _ CInt(textBoxNumberAttempts.Text) 'Show the number of iterations we are going to perform ListBox1.Items.Add("=>" + numberItterations.ToString() + _ " Iterations") Dim count_SumLessThanZero As Integer Dim dataOut As Integer '----------------------------------------------------------- 'Start the performance timer '----------------------------------------------------------- PerformanceSampling.StartSample(TEST_NUMBER, _ "Catch Exception") '----------------------------------------------------------- 'Run the loop that calls the function '----------------------------------------------------------- count_SumLessThanZero = 0 Dim sumGreaterThanZero As Boolean Dim i As Integer While (i < numberItterations) Try '======================= 'Call the test function! '======================= sumGreaterThanZero = _ exceptionIfLessThanZero_Add2Numbers(-2, -3, dataOut) Catch count_SumLessThanZero = count_SumLessThanZero + 1 End Try i = i + 1 End While 'end of loop '----------------------------------------------------------- 'Stop the performance timer '----------------------------------------------------------- PerformanceSampling.StopSample(TEST_NUMBER) '----------------------------------------------------------- 'Output the results to the user '----------------------------------------------------------- If (count_SumLessThanZero = numberItterations) Then MsgBox("Test Passed") ListBox1.Items.Add( _ PerformanceSampling.GetSampleDurationText(TEST_NUMBER)) Else MsgBox("Something is wrong with the test") End If End Sub
|