Kapitel 13: Programmschnittstellen
Zeitmessungen in Access durchführen
API-Programmierung; QueryPerformanceCounter-, QueryPerformanceFrequency-Funktion; Programmie-
rung von Klassen
Wer hatte nicht schon einmal das Problem, die Ausführungsgeschwindigkeit von Programmteilen messen
zu müssen? Sei es nur, um einen Vergleich durchzuführen oder um die Performance von Abfragen zu ver-
bessern. Insbesondere bei Client/Server-Anwendungen kann ein Optimum an Geschwindigkeit nur durch
entsprechende Versuche erreicht werden.
Unter Windows bieten sich verschiedene Varianten an, von denen jedoch nur eine als geeignet angesehen
werden kann. Viele Programmierer verwenden nach wie vor die Funktion GetTickCount, die jedoch eine
völlig unzureichende Genauigkeit liefert. Ursache ist nicht etwa die Funktion an sich, sondern der abgefrag-
te Counter. Geht es nur darum, die Ausführungsgeschwindigkeit weniger Anweisungen zu ermitteln, dürfte
die Ungenauigkeit viel zu groß sein.
Eine Alternative bietet sich mit der Funktion QueryPerformanceCounter, die einen »High Resolution Coun-
ter« abfragt.
Um die genaue Auflösung des Timers zu ermitteln, bedienen Sie sich der Funktion QueryPerformance-
Frequency, welche die Timer-Frequenz zurückgibt. Leider besteht für den Visual Basic-Programmierer an
dieser Stelle ein kleines Problem, der Parameter ist vom C-Datentyp LARGE_INTEGER, den Sie in VBA
vermissen werden. Die Funktions-Abfrage selbst ist noch relativ einfach bewerkstelligt, mit einem Record
kann auch dieser Datentyp abgefragt werden:
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type
Zum Rechnen müssen wir diesen Record allerdings in einen
Double
-Datentyp umwandeln. Diese Aufgabe
übernimmt die Funktion
D
:
Private Function D(x As LARGE_INTEGER) As Double
D = x.lowpart + x.highpart * 4294967296#
End Function
Die o.g. API-Funktionen werden wir in einem Klassenmodul kapseln, folgende Methoden werden bereitge-
stellt:
Methode/Eigenschaft Beschreibung
Calibrieren Dient der Initialisierung des Timers (die Klasse wird initialisiert, gleichzeitig wird ein Korrekturfaktor berechnet, der
Programmlaufzeiten innerhalb des Timers berücksichtigt).
Start Beginn der Zeitmessung.
Halt Ende der Zeitmessung.
ShowTime Anzeige der Laufzeit in Millisekunden.
RunTime Rückgabe der Laufzeit in Millisekunden (Double-Wert)
Tabelle 13.6 Methoden/Eigenschaften des Klassenmoduls
882
Quelltext (Klassendefinition)
Fügen Sie folgenden Quellcode in ein neues Klassenmodul ein und speichern Sie dieses unter dem Namen
»Timer«:
Option Explicit
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type
Interne Variablen zur Berechnung der Zeitdifferenz:
Dim startzeit As LARGE_INTEGER
Dim endzeit As LARGE_INTEGER
Dim frequenz As LARGE_INTEGER
Dim cali As Double
Die API-Deklarationen:
Private Declare Function QueryPerformanceCounter Lib "kernel32" _
(lpPerformanceCount As LARGE_INTEGER) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" _
(lpFrequency As LARGE_INTEGER) As Long
Bei der ersten Verwendung der
Timer
-Klasse wird die
Initialize
-Methode abgearbeitet, in der die Hardware-
timer-Frequenz bestimmt wird:
Private Sub Class_Initialize()
QueryPerformanceFrequency frequenz
End Sub
Vor der Verwendung des Timers sollten Sie diesen kalibrieren, d.h., wir berechnen einen Korrekturfaktor, der
in die Berechnung des Endergebnisses eingeht:
Public Sub Calibrieren()
QueryPerformanceCounter startzeit
QueryPerformanceCounter endzeit
cali = (D(endzeit) - D(startzeit)) / D(frequenz) * 1000 ' ms
End Sub
Starten des Timers:
Public Sub Start()
QueryPerformanceCounter startzeit
End Sub
Anhalten bzw. Ende der Zeitmessung:
Public Sub Halt()
QueryPerformanceCounter endzeit
End Sub
883
Praxisbeispiele
Kapitel 13: Programmschnittstellen
Zur Abfrage des Timer-Wertes definieren wir die schreibgeschützte Eigenschaft
Runtime
:
Public Property Get RunTime() As Variant ' in ms
RunTime = (D(endzeit) - D(startzeit)) / D(frequenz) * 1000 - cali
If RunTime < 0 Then RunTime = 0
End Property
Eine weitere Variante zur Zeitanzeige bietet sich mit der Methode
ShowTime
:
Public Sub ShowTime()
MsgBox "Zeitmessung: " & Format(RunTime, "0.00 ms")
End Sub
Die Konvertierungsfunktion (
LARGE_INTEGER
in
Double
):
Private Function D(x As LARGE_INTEGER) As Double
D = x.lowpart + x.highpart * 4294967296#
End Function
Oberfläche (Beispielprogramm)
Ein kleines Beispielprogramm zeigt die Verwendung der Klasse Timer. Erstellen Sie ein neues Formular,
den prinzipiellen Aufbau zeigt die Abbildung:
Abbildung 13.36 Beispielprogramm (Entwurfsansicht)
Quelltext (Beispielprogramm)
Die folgenden Beispiele zeigen Ihnen, wie Sie den Timer im Zusammenhang mit Berechnungen und Daten-
bank-Abfragen einsetzen können:
Option Explicit
Private Sub Befehl13_Click()
Dim rs As DAO.Recordset
Dim db As DAO.Database
Timer.Calibrieren
Timer.Start
Set db = CurrentDb()
Set rs = db.OpenRecordset("Städte und Telefonvorwahl", dbOpenTable)
While Not rs.EOF
rs.MoveNext
Wend
884
HINWEIS
Timer.Halt
Timer.ShowTime
End Sub
Private Sub Befehl14_Click()
Dim rs As DAO.Recordset
Dim db As DAO.Database
Timer.Calibrieren
Timer.Start
Set db = CurrentDb()
Set rs = db.OpenRecordset("Select * From [Städte und Telefonvorwahl]", dbOpenDynaset)
rs.FindFirst " ort >= 'Burg'"
Timer.Halt
MsgBox "Burgs-Vorwahl ist: " & rs!vorwahl
Timer.ShowTime
End Sub
Private Sub Befehl2_Click()
Dim s As Single
Dim l As Long
Timer.Calibrieren
Timer.Start
For l = 0 To 100000
s = Sqr(123456789)
Next
Timer.Halt
Timer.ShowTime
End Sub
Private Sub Befehl3_Click()
Dim rs As Recordset
Dim db As Database
Timer.Calibrieren
Timer.Start
Set db = CurrentDb()
Set rs = db.OpenRecordset("Städte und Telefonvorwahl", dbOpenTable)
rs.Index = "Ort"
rs.Seek ">=", "Burg"
Timer.Halt
MsgBox "Burgs-Vorwahl ist: " & rs!vorwahl
Timer.ShowTime
End Sub
Test
Führen Sie immer mehrere Zeitmessungen durch, um den Einfluss des Caches bzw. die Ladezeiten von
Libraries zu berücksichtigen.
Beenden Sie gegebenenfalls kurzzeitig Access und starten Sie die Anwendung danach erneut!
885
Praxisbeispiele

Get Microsoft Office Access 2007-Programmierung - Das Handbuch now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.