Czy w języku VBA jest kod, którym mogę zawinąć funkcję, która poinformuje mnie o czasie jej uruchomienia, aby móc porównać różne czasy działania funkcji?
Czy w języku VBA jest kod, którym mogę zawinąć funkcję, która poinformuje mnie o czasie jej uruchomienia, aby móc porównać różne czasy działania funkcji?
Odpowiedzi:
Jeśli twoje funkcje nie są bardzo wolne, będziesz potrzebować timera o bardzo wysokiej rozdzielczości. Najdokładniejszy, jaki znam, to QueryPerformanceCounter
. Google to, aby uzyskać więcej informacji. Spróbuj wypchnąć następujące elementy do klasy, nazwij to CTimer
powiedz, a następnie możesz ustawić instancję w dowolnym miejscu globalnym i po prostu wywołać .StartCounter
i.TimeElapsed
Option Explicit
Private Type LARGE_INTEGER
lowpart As Long
highpart As Long
End Type
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long
Private m_CounterStart As LARGE_INTEGER
Private m_CounterEnd As LARGE_INTEGER
Private m_crFrequency As Double
Private Const TWO_32 = 4294967296# ' = 256# * 256# * 256# * 256#
Private Function LI2Double(LI As LARGE_INTEGER) As Double
Dim Low As Double
Low = LI.lowpart
If Low < 0 Then
Low = Low + TWO_32
End If
LI2Double = LI.highpart * TWO_32 + Low
End Function
Private Sub Class_Initialize()
Dim PerfFrequency As LARGE_INTEGER
QueryPerformanceFrequency PerfFrequency
m_crFrequency = LI2Double(PerfFrequency)
End Sub
Public Sub StartCounter()
QueryPerformanceCounter m_CounterStart
End Sub
Property Get TimeElapsed() As Double
Dim crStart As Double
Dim crStop As Double
QueryPerformanceCounter m_CounterEnd
crStart = LI2Double(m_CounterStart)
crStop = LI2Double(m_CounterEnd)
TimeElapsed = 1000# * (crStop - crStart) / m_crFrequency
End Property
TimeElapsed()
podaje wynik w milisekundach. Nie wdrożyłem żadnej kompensacji kosztów ogólnych, ponieważ bardziej martwiłem się efektem jąkania w obliczeniach narzutów niż idealną dokładnością.
GetTickCount
z kernel32).
StartCounter
And TimeElapsed
? Zrobiłem instancję Timer CTimer
na początku i With StartCounter
po prostu napisałem .StartCounter
po rozpoczęciu mojego subwoofera .TimeElapsed
i odpowiedział mi Invalid use of property
. Kiedy nie mówiąc .StartCounter
już o tym, mówi mi, że obiekt nie jest ustawiony.
Declare PtrSafe Function
stackoverflow.com/questions/21611744/ ...
Funkcja Timer w VBA podaje liczbę sekund, które upłynęły od północy, do 1/100 sekundy.
Dim t as single
t = Timer
'code
MsgBox Timer - t
Jeśli próbujesz zwrócić czas jak stoper, możesz użyć następującego interfejsu API, który zwraca czas w milisekundach od uruchomienia systemu:
Public Declare Function GetTickCount Lib "kernel32.dll" () As Long
Sub testTimer()
Dim t As Long
t = GetTickCount
For i = 1 To 1000000
a = a + 1
Next
MsgBox GetTickCount - t, , "Milliseconds"
End Sub
po http://www.pcreview.co.uk/forums/grab-time-milliseconds-included-vba-t994765.html (ponieważ timeGetTime w winmm.dll nie działał dla mnie, a QueryPerformanceCounter był zbyt skomplikowany dla potrzebnego zadania)
Public Declare Function ...
część? Tworzy błąd podczas dodawania kodu na dole mojego
W przypadku nowicjuszy te linki wyjaśniają, jak wykonać automatyczne profilowanie wszystkich subskrybentów, które chcesz monitorować czas:
http://www.nullskull.com/a/1602/profiling-and-optimizing-vba.aspx
http://sites.mcpher.com/share/Home/excelquirks/optimizationlink patrz procProfiler.zip w http://sites.mcpher.com/share/Home/excelquirks/downlable-items
Sub Macro1()
Dim StartTime As Double
StartTime = Timer
''''''''''''''''''''
'Your Code'
''''''''''''''''''''
MsgBox "RunTime : " & Format((Timer - StartTime) / 86400, "hh:mm:ss")
End Sub
Wynik:
RunTime: 00:00:02
Przez wiele lat korzystaliśmy z rozwiązania opartego na timeGetTime w winmm.dll z dokładnością do milisekund. Zobacz http://www.aboutvb.de/kom/artikel/komstopwatch.htm
Artykuł jest w języku niemieckim, ale kod pobierany (klasa VBA opakowująca wywołanie funkcji dll) jest wystarczająco prosty w użyciu i zrozumieniu bez możliwości przeczytania artykułu.
Sekundy z 2 miejscami po przecinku:
Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) / 1000000, "#,##0.00") & " seconds") 'end timer
Milisekundy:
Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime), "#,##0.00") & " milliseconds") 'end timer
Milisekundy z separatorem przecinków:
Dim startTime As Single 'start timer
MsgBox ("run time: " & Format((Timer - startTime) * 1000, "#,##0.00") & " milliseconds") 'end timer
Zostawiam to tutaj dla każdego, kto szukał prostego timera sformatowanego z sekundami do 2 miejsc po przecinku, tak jak ja. Są to krótkie i słodkie małe timery, których lubię używać. Zajmują tylko jedną linię kodu na początku podrzędnej lub funkcji i jedną linię kodu ponownie na końcu. To nie ma być szalenie dokładne, generalnie nie obchodzi mnie nic mniej niż 1/100 sekundy osobiście, ale licznik milisekund da ci najdokładniejszy czas działania tych trzech. może uzyskać nieprawidłowy odczyt, jeśli zdarzy się, że biegnie podczas przekraczania północy, rzadki przypadek, ale tylko do Twojej wiadomości.