2. Mai 2022

Ausführungsdauer von VBA-Steuerungen messen

In diesem Tipp & Trick geht es um den Einsatz eines VBA Timers zur Messung der Ausführungsdauer von VBA Steuerungen. Um die Perfomance eines Modells zu überprüfen und zu verbessern, ist es von Vorteil, einen Timer zu nutzen, der die Ausführungsdauer von VBA Code misst. So lässt sich zum Beispiel bestimmen, welche Steuerungen besonders viel Rechenzeit benötigen.

Eine zusätzliche VBA-Klasse

Der Timer basiert auf einer in VBA selbst-definierten Klasse namens CTimer. Der Code für die Klasse stammt im Original von Stackoverflow (Klasse CTimer) und wurde für den Gebrauch in WWB-COM und WWB.NET angepasst. Die Klasse und ein Demomodel sind hier im Downloadbereich zu finden (siehe unten). Der Code der Klasse muss zur Nutzung in ein separates Makro eingefügt werden. In der Klasse CTimer kann die Methode CTimer.startCounter aufgerufen werden, um den Timer zu starten. Mit der Eigenschaft CTimer.TimeElapsed wird die vom Start des Timers vergangene Zeit in Millisekunden ausgelesen.

Die Ausführungsdauer messen

In einfachen Beispielen wollen wir zeigen, welchen Einfluss unterschiedliche Syntax auf die Ausführungsdauer einer VBA-Steuerung hat. Um die gemessene Zeit in einer Tabelle zu speichern, wird in diesen Beispielen die Subroutine Store_Measured_Time aufgerufen. In dieser Subroutine wird die Zeit für die Ausführung eines gemessenen VBA Codes für alle seine Aufrufe aufsummiert. Zusätzlich wird die maximale Ausführungszeit, die Anzahl an Aufrufen und die durchschnittliche Ausführungsdauer für die Steuerung gespeichert und in eine Tabelle geschrieben. Falls es für den gemessenen Code noch keine Zeile in der Tabelle gibt, wird eine neue eingefügt. Diese Subroutine hat den Namen der gemessenen Steuerung und die Timer Variable der Klasse Timer als Argument:

Sub Store_Measured_Time(measured_sub_name As String, ByRef sub_timer As CTimer) 'time_elapsed As Double) 
        
        Dim time_elapsed As Double
        time_elapsed = sub_timer.TimeElapsed 'read out the passed time
    
        Dim row As Long
        row = t_Timer.FindRow(measured_sub_name) 'look in the table if there is already a line for the sub
    
        If row < 0 Then 'if there is no line for the sub yet
            row = t_Timer.RowCount + 1
            t_Timer(row,0) = measured_sub_name
            t_Timer(row,"Total Time [ms]") = 0
            t_Timer(row,"Number") = 0
            t_Timer(row,"Mean [ms]") = 0
            t_Timer(row,"Max [ms]") = 0
        End If
    
        t_Timer(measured_sub_name,"Total Time [ms]") += time_elapsed 'add the elapsed time
        t_Timer(measured_sub_name,"Number") += 1 'count the calls of the sub
        t_Timer(measured_sub_name,"Mean [ms]") =  t_Timer(measured_sub_name,"Total Time [ms]")/t_Timer(measured_sub_name,"Number") 'calculate the mean duration of the sub
    
        If time_elapsed > t_Timer(measured_sub_name,"Max [ms]") Then
            t_Timer(measured_sub_name,"Max [ms]") = time_elapsed 'saves the maximum time
        End If

End Sub

Dieses Sub stellt ist nur ein Bespiel dafür, wie man die Ergebnisse des Timers auswerten kann. Natürlich kann der Code den persönlichen Wünschen entsprechend angepasst und eigene KPIs berechnet werden.

Wenn Store_Measured_Time so genutzt werden soll, muss die Tabelle t_Timer z. B. in der Simulationsinitialisierung zunächst initiiert werden.

Dim t_Timer As Table
Private Sub Simulation_Init() Handles Simulation.Init
    t_Timer = New Table
    t_Timer = Read_Table("Timer Template",1,1,0,0,True,True)
End Sub

Im Downloadbereich befindet sich ein Beispielprojekt, bei dem das Parameterworkbook das Tabellenblatt Timer Template enthält, welches eine leere Tabelle mit den gewünschten Überschriften (Procedures, Total Time [ms], etc.) ist.

Beispiele

Zwei Schreibweisen von If-Statements vergleichen

Im ersten Beispiel wird die Syntax von If-Abfragen in einer Start-Steuerung überprüft.

'Version 1:
Sub OP_Start1(cop As OrderOperation)
    Dim sub_timer As New CTimer
    sub_timer.StartCounter 'starts the counter

    If cop.Unit.Allocated = True Then
        'do nothing
    End If

    Store_Measured_Time("OP_Start1",sub_timer)
End Sub
'Version 2:
Sub OP_Start2(cop As OrderOperation)
    Dim sub_timer As New CTimer
    sub_timer.StartCounter 'starts the counter

    If cop.Unit.Allocated Then
        'do nothing
    End If

    Store_Measured_Time("OP_Start2",sub_timer)
End Sub

In der Ergebnistabelle ist zu sehen, dass die erste Version der Steuerung etwas langsamer ist als die zweite. Die maximale Ausführungsdauer, die mittlere Dauer und die gesamte Dauer sind ebenfalls für die gleiche Anzahl an Aufrufen größer.

Procedures Total Time [ms] Number Mean [ms] Max [ms]
OP_Start1 1,1016 100 0,011016 0,0569
OP_Start2 0,5958 100 0,005958 0,0102

Bitte beachten: Alle Werte sind spezifisch für den verwendeten Computer und des aktuellen Status des Computers.

Vergleich von zwei Schreibweisen für Rechenoperationen

In dem zweiten Beispiel werden zwei Versionen für die Syntax für das Verdoppeln der Operationsdauer in einer Parametersteuerung verglichen.

'Version 1:
Sub OP_Parameter1(cop As OrderOperation, mop As RecipeOperation)

    Dim sub_timer As New CTimer
    sub_timer.StartCounter

    cop.Duration = cop.Duration * 2

    Store_Measured_Time("OP_Parameter1",sub_timer)
End Sub
'Version 2:
Sub OP_Parameter2(cop As OrderOperation, mop As RecipeOperation)

    Dim sub_timer As New CTimer
    sub_timer.StartCounter

    cop.Duration *= 2

    Store_Measured_Time("OP_Parameter2",sub_timer)
End Sub

In den Ergebnissen ist zu sehen, dass die zweite Version fast doppelt so schnell ist, wie die erste. Der Maximalwert für die Ausführung der Steuerung ist für beide Versionen vergleichbar, aber die Gesamtausführungszeit und die Durchschnittszeit unterscheiden sich sehr.

Procedures    Total Time [ms] Number Mean [ms] Max [ms]
OP_Parameter1 1,1806 100 0,011806 0,0282
OP_Parameter2 0,6375 100 0,006375 0,0278

Bitte beachten: Alle Werte sind spezifisch für den verwendeten Computer und des aktuellen Status des Computers.

Teilanlagenbelegungssteuerung V12 vs. V13

In einem weiteren Beispiel wird das Verhalten von Teilanlagenbelegungssteuerung verglichen. Der Tipp & Trick Neue Steuerungen für Unit Pools in INOSIM 13 anwenden beschreibt das unterschiedliche Verhalten der Steuerung detailliert. In der ersten Version wird das alte Standardverhalten von INOSIM 12 genutzt. Dabei wird die Steuerung wiederholt aufgerufen und eine Teilanlage vorgeschlagen, diese kann zugelassen oder abgelehnt werden. Falls die vorgeschlagene Teilanlage abgelehnt wird, wird die Steuerung für eine andere Teilanlage wieder aufgerufen. Ab INOSIM 13 ist es möglich im ersten Aufruf der Steuerung zu bestimmen, welche Teilanlagen erlaubt sind. Dann wird nur ein Aufruf benötigt. Welchen Geschwindigkeitsvorteil bietet diese Möglichkeit?

Procedures    Total time [ms] Number Mean [ms] Max [ms]
Product_Tank_V12 17124,2879 399329 0,04288266 219,431
Product_Tank_V13 660,2568 3901 0,16925322 0,9836

Bitte beachten: Alle Werte sind spezifisch für den verwendeten Computer und des aktuellen Status des Computers.

Die durchschnittliche Ausführungszeit für die V12-Variante beträgt nur ungefähr ein Viertel der V13-Steuerung. Die Steuerung wird allerdings ca. 100-mal häufiger aufgerufen als die V13-Version, da sie mehrfach aufgerufen wird, bis eine passende Teilanlage gefunden wurde. Insgesamt ergibt sich daher in diesem konkreten Anwendungsfall ein 25-facher Geschwindigkeitsvorteil für die V13-Steuerung.

Randnotiz

Beachten Sie, dass das Messen der Ausführungszeit selbst auch zusätzliche Rechenzeit benötigt. Falls der VBA Code zum Starten des Timers und zum Speichern der Werte nicht mehr benötigt wird, sollten die entsprechenden Zeilen auskommentiert oder gelöscht werden. Alternativ kann man einen globalen Schalter nutzen, der den VBA-Timer an- und ausschaltet.

Downloads

(nur für registrierte INOSIM Kunden)

  • Beispielmodell VBA Timer.xml
  • CTimer Klassencode
  • PDF-Ausdruck dieses Tipps & Tricks

Fragen?

Möchten Sie mehr über dieses Thema erfahren oder haben weitere Fragen? Bitte kontaktieren Sie uns.

Array ( [posts_per_page] => 3 [post_type] => [category__in] => Array ( [0] => 171 ) [orderby] => rand [order] => ASC )

Mehr Tipps & Tricks

In der Prozessindustrie ist es nicht ungewöhnlich, dass sich der Bedarf an Ressourcen über eine Prozessoperation ändert. Typische Beispiele hierfür sind Kühlmäntel von Reaktoren, in…

In diesem Tipp zeigen wir Ihnen, wie Sie einen ausgewählten Zeitbereich eines umfangreichen Gantt-Diagramms als PDF ausgeben und Ihr Firmenlogo in die Kopfzeile einfügen. Das INOSIM…

Dieser Tipp & Trick beschreibt eine Vielzahl von Methoden zur Vermeidung und Behandlung von Laufzeitfehlern in Ihrem VBA-Code. Sie werden mit den FindColumn– und FindRow-Methoden…

mehr

INOSIM Kontakt

Zu den lokalen Geschäftszeiten

Deutschland +49 231 97 00 250