Benchmarking VBA Code
The following code uses a windows function that is more accurate than Excel. It is taken from http://msdn.microsoft.com/en-us/library/aa730921.aspx#Office2007excelPerf_MakingWorkbooksCalculateFaster. The same page also contains some great tips on improving performance in Excel 2007.
Private Declare Function getFrequency Lib "kernel32" _
Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long
Private Declare Function getTickCount Lib "kernel32" _
Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long
Function MicroTimer() As Double
'Returns seconds.
Dim cyTicks1 As Currency
Static cyFrequency As Currency
MicroTimer = 0
' Get frequency.
If cyFrequency = 0 Then getFrequency cyFrequency
' Get ticks.
getTickCount cyTicks1
' Seconds
If cyFrequency Then MicroTimer = cyTicks1 / cyFrequency
End Function
Interesting question. This is not really a full answer but this is too long to be posted as a comment.
What i use is this kind of procedure:
Option Explicit
Public Time As Double
Sub Chrono()
If Time = 0 Then
Time = Now()
Else
MsgBox "Total time :" & Application.Text(Now() - _
Time, "mm:ss") & "." 'or whatever if not a msgbox
Time = 0
End If
End Sub
That way, you can put your code wherever you want and only have to call it twice (for instance):
If C_DEBUG Then Call Chrono
At the beginning and at the end of the part of code you want to test.
Yet, i would say there is no real "accurate" method because it also depends on what is running on your computer. I'd say these methods would mostly help telling which code is better than another.
Any measurement is going to be noisy, so if you want precision, repeat the measurement many times and average the result.
Professional Excel Development contains a dll utility PerfMon
that I prefer, for its accuracy, and as it can be easily inserted throughout code with a couple of menu clicks
As RonnieDickson answered the QueryPerformanceCounter function is the most accurate possible way to bench VBA code (when you don't want to use a dll, like brettdj suggested). I wrote a class that makes that function easy to use: only initialize the benchmark class + call the method in between your code. No need to write code for substracting times, re-initializing times and writing to debug for example.
Sub TimerBenchmark()
Dim bm As New cBenchmark
'Some code here
bm.Wait 0.0001
bm.TrackByName "Some code"
'Some more (time consuming) code here
bm.Wait 0.04
bm.TrackByName "Bottleneck code"
End Sub
Which would automatically print a readable table to the Immediate window:
IDnr Name Count Sum of tics Percentage Time sum
0 Fast code 1 25.136 5,91% 2,51 ms
1 Bottleneck code 1 400.316 94,09% 40 ms
TOTAL 2 425.452 100,00% 43 ms
Total time recorded: 43 ms
The class includes a .Wait function, which does the same as Application.Wait, but requires only an input in seconds, instead of a time value. It is used above to simulate some code.
https://github.com/jonadv/VBA-Benchmark