gpt4 book ai didi

vba - 一般来说,哪个会产生更好的性能?

转载 作者:行者123 更新时间:2023-12-03 17:38:52 25 4
gpt4 key购买 nike

我有一个小难题。众所周知,按类型定义变量并避免使用变体是最明显的性能技巧。问题是我正在尝试编写一个可以处理隐式类型参数(基本上是变体)的例程库。

举个例子:

Sub Test(A As String) ' Implicit ByRef
Debug.Print A
End Sub

没什么疯狂的,对吧?如果我这样做了 Test "ABC" ,它按预期工作。当我尝试从数组( Test Array("ABC")(0) )传递一个值,甚至在链接时从另一个例程传递一个返回值时,就会出现问题。我会收到一个编译错误,说“ByRef 参数类型不匹配”。

我需要这些例程来接受各种类型的参数并在可能的情况下对它们进行类型转换。然后我想到了以下几点:
Sub Test(ByVal A As String) ' Explicit ByVal
Debug.Print A
End Sub

现在它工作正常。所以最终,我的问题是:通过显式定义参数类型所获得的性能增益是否值得权衡使用 ByVal 复制参数值所带来的性能损失? ?我知道会有一种情况会比另一种更好,但是对于一般用途的库,哪种方法更合适?

我已经设置了一个小基准。我并没有完全使用世界上最强大的计算机(Core i3-2120、32 位 Windows 7、4 GB RAM),所以我不能说这些将适用于其他设置。
Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long

Private Sub NoOp(ParamArray Self()) ' Adds a small overhead; not sure if there's a better built-in routine to use
End Sub

Private Sub ByReference(ByRef Argument As Variant) ' ByRef and As Variant are the default keywords if all keywords are ignored
NoOp Argument
End Sub

Private Sub ByValue(ByVal Argument As String)
NoOp Argument
End Sub

Private Sub Benchmark()
Dim Index As Long, Argument As Variant: Argument = "ABC"
A = GetTickCount / 1000
For Index = 1 To 10000000
ByReference Argument
Next
B = GetTickCount / 1000
For Index = 1 To 10000000
ByValue Argument
Next
Debug.Print B - A, (GetTickCount / 1000) - B ' Seconds; we get higher precision if we divide them before taking their differences
End Sub

结果: 3.88499999999476 4.99199999999837
我们可以看到字符串的性能损失非常明显(无论如何都是短的)。

现在,如果我更改 Argument12345例程定义的参数类型为 Long ,我得到:

结果: 4.07200000000012 4.05599999999686
我不知道这是否在误差范围内,但它确实告诉我们不同类型的行为会有所不同。

随意在您自己的系统上尝试不同的类型并告诉我。

最佳答案

我做了一个快速测试,看看下面。调用ByRef更快,这不足为奇,但是时间太短了,通常你真的不必关心。用三年前的笔记本电脑在 Win7 上测试,所以没什么特别的。

运行 100 万次迭代,ByRef 的结果为 141 毫秒ByVal 为 281 毫秒.每隔一次更改用作参数的字符串会增加时间,但是对于这两种方法,我认为这是由于字符串处理造成的。

我的结论:根据您的需要选择调用方法,而不是速度。

Option Explicit

Private mlngStart As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long

Sub test()

testPerformance 1000000, False
testPerformance 1000000, True

End Sub

Sub testPerformance(iterations, changeString)
Dim s As String
s = "Hello World, this is a really long string to test what will happen when we pass it by value"
StartTimer
Dim i As Long
For i = 1 To iterations
If changeString Then s = IIf(i Mod 2 = 0, "Hello world", "Hello World, this is a really long string to test what will happen when we pass it by value")
Call f1(s)
Next i
Debug.Print iterations, changeString, "ByRef: " & EndTimer

StartTimer
For i = 1 To iterations
If changeString Then s = IIf(i Mod 2 = 0, "Hello world", "Hello World, this is a really long string to test what will happen when we pass it by value")
Call f2(s)
Next i
Debug.Print iterations, changeString, "ByVal: " & EndTimer

End Sub

Sub f1(ByRef s As String)
'
If s = "X" Then
Debug.Print s
End If
End Sub

Sub f2(ByVal s As String)
If s = "X" Then
Debug.Print s
End If
End Sub

Public Sub StartTimer()
mlngStart = GetTickCount
End Sub

Public Function EndTimer() As Long
EndTimer = (GetTickCount - mlngStart)
End Function

输出:
 1000000      False         ByRef: 141
1000000 False ByVal: 281
1000000 True ByRef: 655
1000000 True ByVal: 764

关于vba - 一般来说,哪个会产生更好的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45303263/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com