SafeArrayCopy SLOWER than iterating string array!
Good day!
Being one of those people who is obsessed with maximising the performance of
repetitive operations, I was looking for alternative ways to copy one string
array to another in VB5. I have previously been writing a functions to
convert a Variant containing a String Array to a String Array, and had used
the SafeArrayCopy function. This then got me thinking that maybe this
function would be a quicker way to copy large string arrays, as happens a
lot in our code. After much messing about, I came up with the following
code, which requires a type library for the VarPtrStringArray() function
(see MSDN Knowledge Base Q199824 - HOWTO: Get the Address of Variables in
Visual Basic) :
-------
Option Explicit
Private Declare Function SafeArrayCopy Lib "oleaut32.dll" ( _
ByVal psa As Long, _
ByVal ppsaOut As Long) As Long
Private Type VARIANT_PTR
vt As Integer
reserved1 As Integer
reserved2 As Integer
reserved3 As Integer
ptr As Long
filler(1 To 4) As Byte
End Type
Public Sub GVariantToStringArray(ByRef v As Variant, _
ByRef s() As String)
' Purpose: Retrieves a string array from a variant.
' Inputs: v
' Outputs: s()
' In/Outs: <None>
' Created: 12/06/2000: MAB
Dim udtVariant As VARIANT_PTR
' Take a copy of the variant to the variant structure.
win.CopyMemory udtVariant, v, 16
' Only allow variant string arrays.
If udtVariant.vt = (vbString Or vbArray) Then
' Ensure that any strings in existance are released.
Erase s()
' Copy the array in the variant over to s().
SafeArrayCopy udtVariant.ptr, VarPtrStringArray(s())
Else
' Raise a Type Mismatch error.
Err.Raise win.VBErrorConst.eeTypeMismatch
End If
End Sub
Public Sub GCopyStringArray(ByRef asSource() As String, _
ByRef asDestination() As String)
' Purpose: Copies the string array, asSource, to asDestination.
' Inputs: asSource
' Outputs: asDestination
' In/Outs: <None>
' Created: 12/06/2000: MAB
Dim ptr As Long
' Destroy asDestination.
Erase asDestination
' Get a pointer to the pointer to asSource.
win.CopyMemory ptr, ByVal VarPtrStringArray(asSource), 4
' Copy data from asSource to asDestination.
SafeArrayCopy ptr, VarPtrStringArray(asDestination)
End Sub
-------
Well, the GCopyStringArray routine works, but in tests, it is approximately
5.5 times slower than simply Redim'ing a new string array, and then copying
strings between the old and new arrays. Most perplexing. Can anybody
explain this big difference in speed?
Thanks,
---------------------------------------
Mark Alexander Bertenshaw
Programmer/Analyst
Prime Response
Brentford
UK
Re: SafeArrayCopy SLOWER than iterating string array!
Not sure what you need to have explained here.... you assume because it uses
APIs it must be faster?
What is, speaks for itself. Such as the numbers you have been given.
--
MichKa
"Cause it's a bittersweet symphony, thats life..." -- The Verve
random junk of dubious value, at the multilingual,
no scripts required, http://www.trigeminal.com/
"Mark Alexander Bertenshaw" <Mark.Bertenshaw@virgin.net> wrote in message
news:39457bdf@news.devx.com...
> Good day!
>
> Being one of those people who is obsessed with maximising the performance
of
> repetitive operations, I was looking for alternative ways to copy one
string
> array to another in VB5. I have previously been writing a functions to
> convert a Variant containing a String Array to a String Array, and had
used
> the SafeArrayCopy function. This then got me thinking that maybe this
> function would be a quicker way to copy large string arrays, as happens a
> lot in our code. After much messing about, I came up with the following
> code, which requires a type library for the VarPtrStringArray() function
> (see MSDN Knowledge Base Q199824 - HOWTO: Get the Address of Variables in
> Visual Basic) :
>
> -------
>
> Option Explicit
>
> Private Declare Function SafeArrayCopy Lib "oleaut32.dll" ( _
> ByVal psa As Long, _
> ByVal ppsaOut As Long) As Long
>
> Private Type VARIANT_PTR
> vt As Integer
> reserved1 As Integer
> reserved2 As Integer
> reserved3 As Integer
> ptr As Long
> filler(1 To 4) As Byte
> End Type
>
> Public Sub GVariantToStringArray(ByRef v As Variant, _
> ByRef s() As String)
> ' Purpose: Retrieves a string array from a variant.
> ' Inputs: v
> ' Outputs: s()
> ' In/Outs: <None>
> ' Created: 12/06/2000: MAB
> Dim udtVariant As VARIANT_PTR
>
> ' Take a copy of the variant to the variant structure.
> win.CopyMemory udtVariant, v, 16
> ' Only allow variant string arrays.
> If udtVariant.vt = (vbString Or vbArray) Then
> ' Ensure that any strings in existance are released.
> Erase s()
> ' Copy the array in the variant over to s().
> SafeArrayCopy udtVariant.ptr, VarPtrStringArray(s())
> Else
> ' Raise a Type Mismatch error.
> Err.Raise win.VBErrorConst.eeTypeMismatch
> End If
>
> End Sub
>
> Public Sub GCopyStringArray(ByRef asSource() As String, _
> ByRef asDestination() As String)
> ' Purpose: Copies the string array, asSource, to asDestination.
> ' Inputs: asSource
> ' Outputs: asDestination
> ' In/Outs: <None>
> ' Created: 12/06/2000: MAB
> Dim ptr As Long
>
> ' Destroy asDestination.
> Erase asDestination
>
> ' Get a pointer to the pointer to asSource.
> win.CopyMemory ptr, ByVal VarPtrStringArray(asSource), 4
> ' Copy data from asSource to asDestination.
> SafeArrayCopy ptr, VarPtrStringArray(asDestination)
>
> End Sub
>
> -------
>
> Well, the GCopyStringArray routine works, but in tests, it is
approximately
> 5.5 times slower than simply Redim'ing a new string array, and then
copying
> strings between the old and new arrays. Most perplexing. Can anybody
> explain this big difference in speed?
>
> Thanks,
>
> ---------------------------------------
> Mark Alexander Bertenshaw
> Programmer/Analyst
> Prime Response
> Brentford
> UK
>
>
Re: SafeArrayCopy SLOWER than iterating string array!
Not sure what you need to have explained here.... you assume because it uses
APIs it must be faster?
What is, speaks for itself. Such as the numbers you have been given.
--
MichKa
"Cause it's a bittersweet symphony, thats life..." -- The Verve
random junk of dubious value, at the multilingual,
no scripts required, http://www.trigeminal.com/
"Mark Alexander Bertenshaw" <Mark.Bertenshaw@virgin.net> wrote in message
news:39457bdf@news.devx.com...
> Good day!
>
> Being one of those people who is obsessed with maximising the performance
of
> repetitive operations, I was looking for alternative ways to copy one
string
> array to another in VB5. I have previously been writing a functions to
> convert a Variant containing a String Array to a String Array, and had
used
> the SafeArrayCopy function. This then got me thinking that maybe this
> function would be a quicker way to copy large string arrays, as happens a
> lot in our code. After much messing about, I came up with the following
> code, which requires a type library for the VarPtrStringArray() function
> (see MSDN Knowledge Base Q199824 - HOWTO: Get the Address of Variables in
> Visual Basic) :
>
> -------
>
> Option Explicit
>
> Private Declare Function SafeArrayCopy Lib "oleaut32.dll" ( _
> ByVal psa As Long, _
> ByVal ppsaOut As Long) As Long
>
> Private Type VARIANT_PTR
> vt As Integer
> reserved1 As Integer
> reserved2 As Integer
> reserved3 As Integer
> ptr As Long
> filler(1 To 4) As Byte
> End Type
>
> Public Sub GVariantToStringArray(ByRef v As Variant, _
> ByRef s() As String)
> ' Purpose: Retrieves a string array from a variant.
> ' Inputs: v
> ' Outputs: s()
> ' In/Outs: <None>
> ' Created: 12/06/2000: MAB
> Dim udtVariant As VARIANT_PTR
>
> ' Take a copy of the variant to the variant structure.
> win.CopyMemory udtVariant, v, 16
> ' Only allow variant string arrays.
> If udtVariant.vt = (vbString Or vbArray) Then
> ' Ensure that any strings in existance are released.
> Erase s()
> ' Copy the array in the variant over to s().
> SafeArrayCopy udtVariant.ptr, VarPtrStringArray(s())
> Else
> ' Raise a Type Mismatch error.
> Err.Raise win.VBErrorConst.eeTypeMismatch
> End If
>
> End Sub
>
> Public Sub GCopyStringArray(ByRef asSource() As String, _
> ByRef asDestination() As String)
> ' Purpose: Copies the string array, asSource, to asDestination.
> ' Inputs: asSource
> ' Outputs: asDestination
> ' In/Outs: <None>
> ' Created: 12/06/2000: MAB
> Dim ptr As Long
>
> ' Destroy asDestination.
> Erase asDestination
>
> ' Get a pointer to the pointer to asSource.
> win.CopyMemory ptr, ByVal VarPtrStringArray(asSource), 4
> ' Copy data from asSource to asDestination.
> SafeArrayCopy ptr, VarPtrStringArray(asDestination)
>
> End Sub
>
> -------
>
> Well, the GCopyStringArray routine works, but in tests, it is
approximately
> 5.5 times slower than simply Redim'ing a new string array, and then
copying
> strings between the old and new arrays. Most perplexing. Can anybody
> explain this big difference in speed?
>
> Thanks,
>
> ---------------------------------------
> Mark Alexander Bertenshaw
> Programmer/Analyst
> Prime Response
> Brentford
> UK
>
>
Re: SafeArrayCopy SLOWER than iterating string array!
Michael -
I fully understand that APIs can be slower than VB code, which is why I bothered
to do the test. However, as a general rule, the hackers who wrote API code
probably have more experience with them than me, and probably know the "guts"
of the routines, and as a result are more likely to have a faster way to
use their more primitive routines than me.
I was just somewhat surprised that my code was 5.5 times faster than theirs.
I would have expected at least something comparable with mine. I am wondering
whether there is something in my code that is bound to slow the API routine
down.
"Michael \(michka\) Kaplan" <former_mvp@spamfree.trigeminal.nospam.com> wrote:
>Not sure what you need to have explained here.... you assume because it
uses
>APIs it must be faster?
>
>What is, speaks for itself. Such as the numbers you have been given.
>
>--
>MichKa
>"Cause it's a bittersweet symphony, thats life..." -- The Verve
>
>random junk of dubious value, at the multilingual,
>no scripts required, http://www.trigeminal.com/
>
>"Mark Alexander Bertenshaw" <Mark.Bertenshaw@virgin.net> wrote in message
>news:39457bdf@news.devx.com...
>> Good day!
>>
>> Being one of those people who is obsessed with maximising the performance
>of
>> repetitive operations, I was looking for alternative ways to copy one
>string
>> array to another in VB5. I have previously been writing a functions to
>> convert a Variant containing a String Array to a String Array, and had
>used
>> the SafeArrayCopy function. This then got me thinking that maybe this
>> function would be a quicker way to copy large string arrays, as happens
a
>> lot in our code. After much messing about, I came up with the following
>> code, which requires a type library for the VarPtrStringArray() function
>> (see MSDN Knowledge Base Q199824 - HOWTO: Get the Address of Variables
in
>> Visual Basic) :
>>
>> -------
>>
>> Option Explicit
>>
>> Private Declare Function SafeArrayCopy Lib "oleaut32.dll" ( _
>> ByVal psa As Long, _
>> ByVal ppsaOut As Long) As Long
>>
>> Private Type VARIANT_PTR
>> vt As Integer
>> reserved1 As Integer
>> reserved2 As Integer
>> reserved3 As Integer
>> ptr As Long
>> filler(1 To 4) As Byte
>> End Type
>>
>> Public Sub GVariantToStringArray(ByRef v As Variant, _
>> ByRef s() As String)
>> ' Purpose: Retrieves a string array from a variant.
>> ' Inputs: v
>> ' Outputs: s()
>> ' In/Outs: <None>
>> ' Created: 12/06/2000: MAB
>> Dim udtVariant As VARIANT_PTR
>>
>> ' Take a copy of the variant to the variant structure.
>> win.CopyMemory udtVariant, v, 16
>> ' Only allow variant string arrays.
>> If udtVariant.vt = (vbString Or vbArray) Then
>> ' Ensure that any strings in existance are released.
>> Erase s()
>> ' Copy the array in the variant over to s().
>> SafeArrayCopy udtVariant.ptr, VarPtrStringArray(s())
>> Else
>> ' Raise a Type Mismatch error.
>> Err.Raise win.VBErrorConst.eeTypeMismatch
>> End If
>>
>> End Sub
>>
>> Public Sub GCopyStringArray(ByRef asSource() As String, _
>> ByRef asDestination() As String)
>> ' Purpose: Copies the string array, asSource, to asDestination.
>> ' Inputs: asSource
>> ' Outputs: asDestination
>> ' In/Outs: <None>
>> ' Created: 12/06/2000: MAB
>> Dim ptr As Long
>>
>> ' Destroy asDestination.
>> Erase asDestination
>>
>> ' Get a pointer to the pointer to asSource.
>> win.CopyMemory ptr, ByVal VarPtrStringArray(asSource), 4
>> ' Copy data from asSource to asDestination.
>> SafeArrayCopy ptr, VarPtrStringArray(asDestination)
>>
>> End Sub
>>
>> -------
>>
>> Well, the GCopyStringArray routine works, but in tests, it is
>approximately
>> 5.5 times slower than simply Redim'ing a new string array, and then
>copying
>> strings between the old and new arrays. Most perplexing. Can anybody
>> explain this big difference in speed?
>>
>> Thanks,
>>
>> ---------------------------------------
>> Mark Alexander Bertenshaw
>> Programmer/Analyst
>> Prime Response
>> Brentford
>> UK
>>
>>
>
>
Re: SafeArrayCopy SLOWER than iterating string array!
Michael -
I fully understand that APIs can be slower than VB code, which is why I bothered
to do the test. However, as a general rule, the hackers who wrote API code
probably have more experience with them than me, and probably know the "guts"
of the routines, and as a result are more likely to have a faster way to
use their more primitive routines than me.
I was just somewhat surprised that my code was 5.5 times faster than theirs.
I would have expected at least something comparable with mine. I am wondering
whether there is something in my code that is bound to slow the API routine
down.
"Michael \(michka\) Kaplan" <former_mvp@spamfree.trigeminal.nospam.com> wrote:
>Not sure what you need to have explained here.... you assume because it
uses
>APIs it must be faster?
>
>What is, speaks for itself. Such as the numbers you have been given.
>
>--
>MichKa
>"Cause it's a bittersweet symphony, thats life..." -- The Verve
>
>random junk of dubious value, at the multilingual,
>no scripts required, http://www.trigeminal.com/
>
>"Mark Alexander Bertenshaw" <Mark.Bertenshaw@virgin.net> wrote in message
>news:39457bdf@news.devx.com...
>> Good day!
>>
>> Being one of those people who is obsessed with maximising the performance
>of
>> repetitive operations, I was looking for alternative ways to copy one
>string
>> array to another in VB5. I have previously been writing a functions to
>> convert a Variant containing a String Array to a String Array, and had
>used
>> the SafeArrayCopy function. This then got me thinking that maybe this
>> function would be a quicker way to copy large string arrays, as happens
a
>> lot in our code. After much messing about, I came up with the following
>> code, which requires a type library for the VarPtrStringArray() function
>> (see MSDN Knowledge Base Q199824 - HOWTO: Get the Address of Variables
in
>> Visual Basic) :
>>
>> -------
>>
>> Option Explicit
>>
>> Private Declare Function SafeArrayCopy Lib "oleaut32.dll" ( _
>> ByVal psa As Long, _
>> ByVal ppsaOut As Long) As Long
>>
>> Private Type VARIANT_PTR
>> vt As Integer
>> reserved1 As Integer
>> reserved2 As Integer
>> reserved3 As Integer
>> ptr As Long
>> filler(1 To 4) As Byte
>> End Type
>>
>> Public Sub GVariantToStringArray(ByRef v As Variant, _
>> ByRef s() As String)
>> ' Purpose: Retrieves a string array from a variant.
>> ' Inputs: v
>> ' Outputs: s()
>> ' In/Outs: <None>
>> ' Created: 12/06/2000: MAB
>> Dim udtVariant As VARIANT_PTR
>>
>> ' Take a copy of the variant to the variant structure.
>> win.CopyMemory udtVariant, v, 16
>> ' Only allow variant string arrays.
>> If udtVariant.vt = (vbString Or vbArray) Then
>> ' Ensure that any strings in existance are released.
>> Erase s()
>> ' Copy the array in the variant over to s().
>> SafeArrayCopy udtVariant.ptr, VarPtrStringArray(s())
>> Else
>> ' Raise a Type Mismatch error.
>> Err.Raise win.VBErrorConst.eeTypeMismatch
>> End If
>>
>> End Sub
>>
>> Public Sub GCopyStringArray(ByRef asSource() As String, _
>> ByRef asDestination() As String)
>> ' Purpose: Copies the string array, asSource, to asDestination.
>> ' Inputs: asSource
>> ' Outputs: asDestination
>> ' In/Outs: <None>
>> ' Created: 12/06/2000: MAB
>> Dim ptr As Long
>>
>> ' Destroy asDestination.
>> Erase asDestination
>>
>> ' Get a pointer to the pointer to asSource.
>> win.CopyMemory ptr, ByVal VarPtrStringArray(asSource), 4
>> ' Copy data from asSource to asDestination.
>> SafeArrayCopy ptr, VarPtrStringArray(asDestination)
>>
>> End Sub
>>
>> -------
>>
>> Well, the GCopyStringArray routine works, but in tests, it is
>approximately
>> 5.5 times slower than simply Redim'ing a new string array, and then
>copying
>> strings between the old and new arrays. Most perplexing. Can anybody
>> explain this big difference in speed?
>>
>> Thanks,
>>
>> ---------------------------------------
>> Mark Alexander Bertenshaw
>> Programmer/Analyst
>> Prime Response
>> Brentford
>> UK
>>
>>
>
>
Re: SafeArrayCopy SLOWER than iterating string array!
Mark,
What happens if you just assign one array to the other. My guess would be
that VB uses SafeArrayCopy to achieve this so it should be slow to.
--
Anthony Jones
Secta Group Ltd
Re: SafeArrayCopy SLOWER than iterating string array!
Mark,
What happens if you just assign one array to the other. My guess would be
that VB uses SafeArrayCopy to achieve this so it should be slow to.
--
Anthony Jones
Secta Group Ltd
Re: SafeArrayCopy SLOWER than iterating string array!
Probably - but I am using VB5, thus the API call.
--
---------------------------------------
Mark Alexander Bertenshaw
Programmer/Analyst
Prime Response
Brentford
UK
"Anthony Jones" <yadayadayada@msn.com> wrote in message
news:394654ff@news.devx.com...
> Mark,
>
> What happens if you just assign one array to the other. My guess would be
> that VB uses SafeArrayCopy to achieve this so it should be slow to.
>
> --
> Anthony Jones
> Secta Group Ltd
>
>
>
Re: SafeArrayCopy SLOWER than iterating string array!
Probably - but I am using VB5, thus the API call.
--
---------------------------------------
Mark Alexander Bertenshaw
Programmer/Analyst
Prime Response
Brentford
UK
"Anthony Jones" <yadayadayada@msn.com> wrote in message
news:394654ff@news.devx.com...
> Mark,
>
> What happens if you just assign one array to the other. My guess would be
> that VB uses SafeArrayCopy to achieve this so it should be slow to.
>
> --
> Anthony Jones
> Secta Group Ltd
>
>
>
Re: SafeArrayCopy SLOWER than iterating string array!
Hi Mark,
When I test the SafeArrayCopy and SafeArrayCopyData functions here, they all
take about the same time as VB's assignment (VB6) or VB's For..Next methods,
for large arrays of strings. (see my code below).
A couple of things.. you don't need a type library to get the pointer for a
string array. See my code below, and/or see July's VBPJ for more details.
Also the safearraycopy is most probably the same as VB's assignment, whereas
safeArrayCopyData would be equivalent of For.. Next loop.
It could be your timings weren't done on a random basis, and hence the
sequence of events favoured one method over the other. Try running the code
I have posted, and you will see which ever method get's called first will
have the fastest time by far but only that one time.. on subsequent calls
all methods tend to be about the same, although the For..Next method seems
to be one or two percent slower.
Note: the timer class used for timings is Karl Peterson's stop watch class
(www.mvps.org/vb)
BTW: it's G'day not "Good day".
Option Explicit
Private Enum ArrayCopyMethods
mCopyNone = 0
mForNext = 1
mVbAssign = 2
mOleCopyData = 3
mOleCopy = 4
End Enum
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SafeArrayCopyData Lib "oleaut32.dll" (ByVal
psaSource As Long, ByVal psaTarget As Long) As Long
Private Declare Function SafeArrayCopy Lib "oleaut32.dll" (ByVal psa As
Long, ByVal ppsaOut As Long) As Long
Private Function GetppSA(vVar As Variant) As Long
CopyMemory GetppSA, ByVal VarPtr(vVar) + 8&, 4&
End Function
Private Function GetpSA(vVar As Variant) As Long
Dim ppSA As Long
CopyMemory ppSA, ByVal VarPtr(vVar) + 8&, 4&
CopyMemory GetpSA, ByVal ppSA, 4&
End Function
Private Function CopyArray(ByRef asIn() As String, _
ByRef asOut() As String, _
ByVal CopyMethod As ArrayCopyMethods) _
As String
Dim i As Long, lngUb As Long
If CopyMethod Then
If CopyMethod And &H2 Then
If CopyMethod And &H1 Then
'mForNext
lngUb = UBound(asIn)
ReDim asOut(lngUb)
For i = 0 To lngUb
asOut(i) = asIn(i)
Next i
CopyArray = "VBForNext"
Else
'mVbAssign
asOut = asIn
CopyArray = "VBAssign"
End If
Else
If CopyMethod And &H1 Then
'mOleCopyData
lngUb = UBound(asIn)
ReDim asOut(lngUb)
SafeArrayCopyData GetpSA(asIn), GetpSA(asOut)
CopyArray = "SafeArrayCopyData"
Else
'mOleCopy
Erase asOut
SafeArrayCopy GetpSA(asIn), GetppSA(asOut)
CopyArray = "SafeArrayCopy"
End If
End If
Else
CopyArray = "function call overhead "
End If
End Function
Sub Main()
Dim s1() As String, s2() As String
Dim lngTime As Long
Dim i As Long, j As Long
Dim ff As Long
Dim strMsg As String
Dim strFile As String
strFile = App.Path
If Right$(strFile, 1) <> "\" Then strFile = strFile & "\"
strFile = strFile & "ArrayCopyTimes.txt"
ReDim s1(10000)
For j = 0 To 9
s1(0 + j * 1000) = "C:\windows\system\" & Dir("C:\windows\system\*.*")
For i = 1 To 1000
s1(i + j * 1000) = "C:\windows\system\" & Dir()
Next i
Next j
Dim cSW As CStopWatch
Set cSW = New CStopWatch
cSW.Reset
Randomize Timer
ff = FreeFile
Open strFile For Output As ff
For i = 0 To 99
j = Rnd * 4
cSW.Reset
strMsg = CopyArray(s1, s2, j)
lngTime = cSW.Elapsed
Print #ff, strMsg, lngTime
If j Then
j = Rnd * 10000
Print #ff, "item " & j
Print #ff, s1(j)
Print #ff, s2(j)
End If
Next i
Close #ff
MsgBox "finished"
End Sub
Re: SafeArrayCopy SLOWER than iterating string array!
Hi Mark,
When I test the SafeArrayCopy and SafeArrayCopyData functions here, they all
take about the same time as VB's assignment (VB6) or VB's For..Next methods,
for large arrays of strings. (see my code below).
A couple of things.. you don't need a type library to get the pointer for a
string array. See my code below, and/or see July's VBPJ for more details.
Also the safearraycopy is most probably the same as VB's assignment, whereas
safeArrayCopyData would be equivalent of For.. Next loop.
It could be your timings weren't done on a random basis, and hence the
sequence of events favoured one method over the other. Try running the code
I have posted, and you will see which ever method get's called first will
have the fastest time by far but only that one time.. on subsequent calls
all methods tend to be about the same, although the For..Next method seems
to be one or two percent slower.
Note: the timer class used for timings is Karl Peterson's stop watch class
(www.mvps.org/vb)
BTW: it's G'day not "Good day".
Option Explicit
Private Enum ArrayCopyMethods
mCopyNone = 0
mForNext = 1
mVbAssign = 2
mOleCopyData = 3
mOleCopy = 4
End Enum
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SafeArrayCopyData Lib "oleaut32.dll" (ByVal
psaSource As Long, ByVal psaTarget As Long) As Long
Private Declare Function SafeArrayCopy Lib "oleaut32.dll" (ByVal psa As
Long, ByVal ppsaOut As Long) As Long
Private Function GetppSA(vVar As Variant) As Long
CopyMemory GetppSA, ByVal VarPtr(vVar) + 8&, 4&
End Function
Private Function GetpSA(vVar As Variant) As Long
Dim ppSA As Long
CopyMemory ppSA, ByVal VarPtr(vVar) + 8&, 4&
CopyMemory GetpSA, ByVal ppSA, 4&
End Function
Private Function CopyArray(ByRef asIn() As String, _
ByRef asOut() As String, _
ByVal CopyMethod As ArrayCopyMethods) _
As String
Dim i As Long, lngUb As Long
If CopyMethod Then
If CopyMethod And &H2 Then
If CopyMethod And &H1 Then
'mForNext
lngUb = UBound(asIn)
ReDim asOut(lngUb)
For i = 0 To lngUb
asOut(i) = asIn(i)
Next i
CopyArray = "VBForNext"
Else
'mVbAssign
asOut = asIn
CopyArray = "VBAssign"
End If
Else
If CopyMethod And &H1 Then
'mOleCopyData
lngUb = UBound(asIn)
ReDim asOut(lngUb)
SafeArrayCopyData GetpSA(asIn), GetpSA(asOut)
CopyArray = "SafeArrayCopyData"
Else
'mOleCopy
Erase asOut
SafeArrayCopy GetpSA(asIn), GetppSA(asOut)
CopyArray = "SafeArrayCopy"
End If
End If
Else
CopyArray = "function call overhead "
End If
End Function
Sub Main()
Dim s1() As String, s2() As String
Dim lngTime As Long
Dim i As Long, j As Long
Dim ff As Long
Dim strMsg As String
Dim strFile As String
strFile = App.Path
If Right$(strFile, 1) <> "\" Then strFile = strFile & "\"
strFile = strFile & "ArrayCopyTimes.txt"
ReDim s1(10000)
For j = 0 To 9
s1(0 + j * 1000) = "C:\windows\system\" & Dir("C:\windows\system\*.*")
For i = 1 To 1000
s1(i + j * 1000) = "C:\windows\system\" & Dir()
Next i
Next j
Dim cSW As CStopWatch
Set cSW = New CStopWatch
cSW.Reset
Randomize Timer
ff = FreeFile
Open strFile For Output As ff
For i = 0 To 99
j = Rnd * 4
cSW.Reset
strMsg = CopyArray(s1, s2, j)
lngTime = cSW.Elapsed
Print #ff, strMsg, lngTime
If j Then
j = Rnd * 10000
Print #ff, "item " & j
Print #ff, s1(j)
Print #ff, s2(j)
End If
Next i
Close #ff
MsgBox "finished"
End Sub