Die Community zu .NET und Classic VB.
Menü

VB.NET-Tipp 0140: Ausführungsgeschwindigkeit von Codeabschnitten bestimmen

 von 

Beschreibung

Bei der Untersuchung der Ausführungsgeschwindigkeit bestimmter Code-Abschnitte zeigt die übliche System.StopWatch eine gewisse Unhandlichkeit, da hin und wieder Zeiten bis hinunter in den Mikrosekunden-Bereich (10^-6 s) zu ermitteln sind. Man kann sich behelfen, indem man die Funktion mehrfach ausführt und somit die Summe der Laufzeiten erhält. Für diese Vorgehensweise sollte man die für einen Durchlauf benötigte Zeit jedoch recht gut abschätzen, da man ansonsten möglicherweise eine viel zu hohe Anzahl von Wiederholungen festlegt und ziemlich lange auf deren Beendingung warten muss.
Dieser Tipp stellt ein besseres Vorgehen vor: Vorgegeben wird eine Zeit und die Schleife wird nach Ablauf derselben verlassen.

Schwierigkeitsgrad:

Schwierigkeitsgrad 1

Framework-Version(en):

.NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Compact Framework 1.0, .NET Compact Framework 2.0, .NET Framework 4

.NET-Version(en):

Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008, Visual Basic 2010

Download:

Download des Beispielprojektes [12,06 KB]

' Dieser Quellcode stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!

' Projektversion:   Visual Studio 2005
' Option Strict:    An
'
' Referenzen: 
'  - System
'  - System.Data
'  - System.Drawing
'  - System.Windows.Forms
'  - System.Xml
'
' Imports: 
'  - Microsoft.VisualBasic
'  - Microsoft.VisualBasic.ControlChars
'  - System
'  - System.Collections
'  - System.Collections.Generic
'  - System.Data
'  - System.Drawing
'  - System.Diagnostics
'  - System.Windows.Forms
'

' ##############################################################################
' ############################# BenchmarkTimer.vb ##############################
' ##############################################################################
''' <summary>
''' Nutzung: eine zeitkritische Funktion mit einer While BenchmarkTimer.Runs()- 
'''   Schleife umschließen. Die Console-Ausgabe gibt an, wie oft die Funktion 
'''   innerhalb der gegebenen Zeit ausgeführt werden konnte
''' </summary>
Public Class BenchmarkTimer
    Private Shared _Counter As Integer
    Private Shared _LastTick As Integer = Integer.MinValue

    Public Shared Function Runs(ByVal RunTime As Integer, _
            Optional ByVal Msg As String = "BenchmarkTimer") As Boolean

        If Environment.TickCount < _LastTick Then
            _Counter += 1
        ElseIf _LastTick = Integer.MinValue Then
            _LastTick = Environment.TickCount + RunTime
            _Counter = 0
        Else
            Console.WriteLine(String.Concat(Msg, ": ", _Counter))
            _LastTick = Integer.MinValue
            Return False
        End If
        Return True
    End Function
End Class
' ##############################################################################
' ########################### BenchmarkWatch.vbproj ############################
' ##############################################################################
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.50727</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{89B5F3CA-7033-4490-9763-21C60FE1DC83}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <StartupObject>BenchmarkWatch.My.MyApplication</StartupObject>
    <RootNamespace>BenchmarkWatch</RootNamespace>
    <AssemblyName>BenchmarkWatch</AssemblyName>
    <MyType>WindowsForms</MyType>
    <OptionStrict>On</OptionStrict>
    <PublishUrl>http://localhost/BenchmarkWatch/</PublishUrl>
    <Install>True</Install>
    <InstallFrom>Web</InstallFrom>
    <UpdateEnabled>True</UpdateEnabled>
    <UpdateMode>Foreground</UpdateMode>
    <UpdateInterval>7</UpdateInterval>
    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
    <UpdatePeriodically>False</UpdatePeriodically>
    <UpdateRequired>False</UpdateRequired>
    <MapFileExtensions>True</MapFileExtensions>
    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
    <IsWebBootstrapper>True</IsWebBootstrapper>
    <BootstrapperEnabled>True</BootstrapperEnabled>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>True</DebugSymbols>
    <DebugType>full</DebugType>
    <DefineDebug>True</DefineDebug>
    <DefineTrace>True</DefineTrace>
    <OutputPath>bin\Debug\</OutputPath>
    <DocumentationFile>BenchmarkWatch.xml</DocumentationFile>
    <NoWarn>
    </NoWarn>
    <WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <DefineDebug>False</DefineDebug>
    <DefineTrace>True</DefineTrace>
    <Optimize>True</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DocumentationFile>BenchmarkWatch.xml</DocumentationFile>
    <NoWarn>
    </NoWarn>
    <WarningsAsErrors>41999,42016,42017,42018,42019,42020,42021,42022,42032,42036</WarningsAsErrors>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Import Include="Microsoft.VisualBasic" />
    <Import Include="Microsoft.VisualBasic.ControlChars" />
    <Import Include="System" />
    <Import Include="System.Collections" />
    <Import Include="System.Collections.Generic" />
    <Import Include="System.Data" />
    <Import Include="System.Drawing" />
    <Import Include="System.Diagnostics" />
    <Import Include="System.Windows.Forms" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="BenchmarkTimer.vb" />
    <Compile Include="frmBenchmarkWatch.vb">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="frmBenchmarkWatch.Designer.vb">
      <DependentUpon>frmBenchmarkWatch.vb</DependentUpon>
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="My Project\AssemblyInfo.vb" />
    <Compile Include="My Project\Application.Designer.vb">
      <AutoGen>True</AutoGen>
      <DependentUpon>Application.myapp</DependentUpon>
    </Compile>
    <Compile Include="My Project\Resources.Designer.vb">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="My Project\Settings.Designer.vb">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="frmBenchmarkWatch.resx">
      <SubType>Designer</SubType>
      <DependentUpon>frmBenchmarkWatch.vb</DependentUpon>
    </EmbeddedResource>
    <EmbeddedResource Include="My Project\Resources.resx">
      <Generator>VbMyResourcesResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.vb</LastGenOutput>
      <CustomToolNamespace>My.Resources</CustomToolNamespace>
      <SubType>Designer</SubType>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <None Include="My Project\Application.myapp">
      <Generator>MyApplicationCodeGenerator</Generator>
      <LastGenOutput>Application.Designer.vb</LastGenOutput>
    </None>
    <None Include="My Project\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <CustomToolNamespace>My</CustomToolNamespace>
      <LastGenOutput>Settings.Designer.vb</LastGenOutput>
    </None>
  </ItemGroup>
  <ItemGroup>
    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
      <Visible>False</Visible>
      <ProductName>.NET Framework 2.0</ProductName>
      <Install>True</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Sql.Server.Express.1.0">
      <Visible>False</Visible>
      <ProductName>SQL Server 2005 Express Edition</ProductName>
      <Install>True</Install>
    </BootstrapperPackage>
    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
      <Visible>False</Visible>
      <ProductName>Windows Installer 3.1</ProductName>
      <Install>True</Install>
    </BootstrapperPackage>
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
  <!-- To modify your build process, add your task inside one Of the targets below And uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
' ##############################################################################
' ########################### frmBenchmarkWatch.vb #############################
' ##############################################################################
Imports System.IO

Public Class frmBenchmarkWatch

    Private Src1 As String, Src2 As String

    Private Sub Form_Load(ByVal sender As Object, ByVal e As EventArgs) _
            Handles MyBase.Load

        Dim DirUp As String = ".." & Path.DirectorySeparatorChar
        Src1 = String.Concat(DirUp, DirUp, "frmBenchmarkWatch.vb")
        Src1 = Path.GetFullPath(Src1)
        Src2 = Application.ExecutablePath
        lbWhatsTested.Text = String.Concat("vergleiche Einlesen der Datei:", _
            Lf, Src1, Lf, "mit Einlesen von:", Lf, Src2)
    End Sub

    Private Sub btTest_Click(ByVal sender As Object, ByVal e As EventArgs) _
            Handles btTest.Click

        ' Teste die Einlese-Geschwindigkeit zweier verschiedener Files
        Dim Buf(&HFF) As Byte
        While BenchmarkTimer.Runs(1000, "load Src1")
            Using FS As New FileStream(Src1, FileMode.Open, FileAccess.Read)
                Do
                    FS.Read(Buf, 0, Buf.Length)
                Loop Until FS.Position = FS.Length
            End Using
        End While
        While BenchmarkTimer.Runs(1000, "load Src2")
            Using FS As New FileStream(Src2, FileMode.Open, FileAccess.Read)
                Do
                    FS.Read(Buf, 0, Buf.Length)
                Loop Until FS.Position = FS.Length
            End Using
        End While
    End Sub

    Private Sub btTestEmpty_Click(ByVal sender As Object, _
            ByVal e As EventArgs) Handles btTestEmpty.Click

        While BenchmarkTimer.Runs(1000, "EmptyTest")
            ' Je größer der Unterschied zwischen Leertest und Echt-Test-
            '  Ergebnissen, desto mehr Aussagekraft haben Letztere
        End While
    End Sub

End Class

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.