【问题标题】:Benchmarking VBA Code基准测试 VBA 代码
【发布时间】:2011-08-18 06:59:11
【问题描述】:

什么被认为是对 VBA 代码进行基准测试的最准确方法(在我的例子中,我在 Excel 中测试代码)?除了下面的 2 种之外,是否还有其他用于对代码进行基准测试的技术,如果有,该方法的优缺点是什么?

这里有 2 种流行的方法。

第一:定时器

Sub TimerBenchmark()

Dim benchmark As Double
benchmark = Timer

'Do your code here

MsgBox Timer - benchmark

End Sub

Tick(我认为这是最准确的):

Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long

Sub TickBenchmark()

Dim Start As Long
Dim Finish As Long

Start = GetTickCount()

'Do your code here

Finish = GetTickCount()
MsgBox CStr((Finish - Start) / 1000)

End Sub

【问题讨论】:

    标签: excel optimization vba benchmarking


    【解决方案1】:

    以下代码使用了比 Excel 更准确的 windows 函数。它取自http://msdn.microsoft.com/en-us/library/aa730921.aspx#Office2007excelPerf_MakingWorkbooksCalculateFaster。同一页面还包含一些关于提高 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
    

    【讨论】:

    • 那篇文章的作者是 Stackoverflow 的常客。他自己的网站有更多关于 Excel 和性能的重要信息:decisionmodels.com
    • 能否请您在答案中总结链接中的代码以防止链接腐烂?此外,提供的微计时器代码似乎不适用于 64 位 Excel。 64 位用户有什么替代方案吗?
    • @StockB FWIW,在 DeclareFunction 之间添加 PtrSafe 用于在 64 位 MS Office 中声明 API 函数。
    【解决方案2】:

    有趣的问题。这不是一个完整的答案,但是太长了,不能作为评论发布。
    我使用的是这种程序:

    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
    

    这样,您可以将代码放在任何您想要的地方,并且只需调用它两次(例如):

    If C_DEBUG Then Call Chrono
    

    在您要测试的代码部分的开头和结尾。

    然而,我想说没有真正的“准确”方法,因为它还取决于您计算机上运行的内容。我想说这些方法主要有助于判断哪个代码比另一个更好

    【讨论】:

      【解决方案3】:

      任何测量都会有噪音,因此如果您想要精确,请重复多次测量并平均结果。

      【讨论】:

        【解决方案4】:

        Professional Excel Development 包含一个我更喜欢的 dll 实用程序 PerfMon,因为它的准确性,而且只需单击几下菜单即可轻松插入到整个代码中

        【讨论】:

          【解决方案5】:

          正如 RonnieDickson 回答的那样,QueryPerformanceCounter 函数是对 VBA 代码进行基准测试的最准确的方法(当您不想使用 dll 时,就像 brettdj 建议的那样)。我编写了一个使该功能易于使用的类:仅初始化基准类+在代码之间调用该方法。无需编写用于减去时间、重新初始化时间和编写调试的代码。

          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
          

          这会自动将可读表格打印到即时窗口:

          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
          

          该类包含一个 .Wait 函数,其作用与 Application.Wait 相同,但只需要以秒为单位的输入,而不是时间值。上面用来模拟一些代码。

          https://github.com/jonadv/VBA-Benchmark

          【讨论】:

          • 似乎很有趣;值得添加最少的有条不紊的提示:+)@jonadv
          • 有条不紊的提示是什么意思?那我应该把写好的类的代码加到这个评论里吗?
          • 不是代码,只是对基本逻辑的简短描述(例如,您如何使用 API 函数,为什么它比其他方法更快,...),可能还有一些示例功能 :-) @乔纳夫
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-03
          • 2012-01-15
          • 2023-02-19
          • 2013-03-10
          • 2021-11-15
          • 1970-01-01
          相关资源
          最近更新 更多