It is possible to use a loop but the performance of it is not that good.
looping will take some time for the copying process to complete as the amount of arrays required in copying and the huge data in each array
Yes, you can simply assign them without referencing an element.
Code:
Public Sub ArrayCopy()
Dim Array1() As Long
Dim Array2() As Long
Dim i As Long
ReDim Array1(9)
ReDim Array2(9)
For i = 0 To 9
Array1(i) = i
Next
Array2 = Array1
Debug.Print Array2(3)
Erase Array1, Array2
End Sub
It is possible to use a loop but the performance of it is not that good.
looping will take some time for the copying process to complete as the amount of arrays required in copying and the huge data in each array
Actually, looping is the fastest way in VB. If you loop VB will optimize an array loop and will copy a the array memory block to the new location and not loop at all.
If you use the statement
Array1 = Array2
VB will do all sorts of bounds checking and structure checks thus slowing it down.
That's because of the different structures in the array. If it were a just a byte array it would work find all other arrays the item structures are stored differently.
<snip>VB will do all sorts of bounds checking and structure checks thus slowing it down.
I was not so sure, at least I thought it would do the checks in both cases.
I tested the following code both in the IDE and Compiled, I think this code is slightly biased towards using the for loop in that I predimension the array before hand.
Code:
Option Explicit
Const ITERATIONS = 10000
Const ARRAYUBOUND = 1023
Dim OldArr() As Long
Dim NewArr() As Long
Public Sub setup()
Dim i As Long
ReDim OldArr(ARRAYUBOUND)
ReDim NewArr(ARRAYUBOUND)
For i = 0 To ARRAYUBOUND
OldArr(i) = i
Next i
End Sub
Sub TestCode1()
Dim i As Long
For i = 1 To ITERATIONS
NewArr = OldArr
Next i
End Sub
Sub TestCode2()
Dim i As Long, ii As Long
For i = 1 To ITERATIONS
For ii = 0 To ARRAYUBOUND
NewArr(ii) = OldArr(ii)
Next ii
Next i
End Sub
In both sets pink represents Array2=Array1 and green represents For... Array2(i)=Array1(i) ...Next. The setup code was not timed.
In the IDE
Compiled (with full compile optimisations for speed)
Numbers can be stored and copied in a block of contiguous memory (they will always be the same size) however string cannot be stored that way and must be checked for length, unicode etc and cannot be moved in the same fashion.
[Quote from http://www.codeproject.com/vb/net/ne...orysample.asp]
CopyMemory is a function that will copy the contents of one block of memory to a different block of memory without regard to the data type that is stored there. This results in an ultra fast copy of data, especially for objects like Structures, Classes and Strings.
Yes, but you must understand how VB stores and references the datatypes. Strings are variable in length so the length cannot be predetermined. You would need to use fixed length strings.
Yes, but you must understand how VB stores and references the datatypes. Strings are variable in length so the length cannot be predetermined. You would need to use fixed length strings.
Faster declarations of memory moving procedures: RtlMoveLong and vbaCopyBytes:
Code:
' Module1.bas: if you rename, see AddressOf lines
Option Explicit
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef lpvDest As Any, ByRef lpvSrc As Any, ByVal cbLen As Long)
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Sub DeclareAPI(ByVal AddressOfDest As Long, ByRef API As String, ByRef Module As String)
Dim lngModuleHandle As Long, AddressOfSrc As Long
Dim larJMPASM(1) As Long
Dim lngProcessHandle As Long, lngBytesWritten As Long
' get handle for module
lngModuleHandle = GetModuleHandle(Module)
If lngModuleHandle = 0 Then lngModuleHandle = LoadLibrary(Module)
' if failed, we can't do anything
If lngModuleHandle = 0 Then Exit Sub
' get address of function
AddressOfSrc = GetProcAddress(lngModuleHandle, API)
' if failed, we can't do anything
If AddressOfSrc = 0 Then Exit Sub
' get a handle for current process
lngProcessHandle = OpenProcess(&H1F0FFF, 0&, GetCurrentProcessId)
' if failed, we can't do anything
If lngProcessHandle = 0 Then Exit Sub
' check if we are in the IDE
If App.LogMode = 0 Then
' get the real location of the procedure
CopyMemory AddressOfDest, ByVal AddressOfDest + &H16&, 4&
End If
' set ASM JMP
larJMPASM(0) = &HE9000000
' set JMP parameter (how many bytes to jump)
larJMPASM(1) = AddressOfSrc - AddressOfDest - 5
' replace original procedure with the JMP
WriteProcessMemory lngProcessHandle, ByVal AddressOfDest, ByVal VarPtr(larJMPASM(0)) + 3, 5, lngBytesWritten
' close handle for current process
CloseHandle lngProcessHandle
End Sub
Public Sub RtlMoveLong(ByVal lpvDest As Long, ByVal lpvSrc As Long, ByVal cbLen As Long)
DeclareAPI AddressOf Module1.RtlMoveLong, "RtlMoveMemory", "ntdll.dll"
RtlMoveLong lpvDest, lpvSrc, cbLen
End Sub
Public Sub vbaCopyBytes(ByVal Length As Long, ByVal dest As Long, ByVal Src As Long)
DeclareAPI AddressOf Module1.vbaCopyBytes, "__vbaCopyBytes", "msvbvm60.dll"
vbaCopyBytes Length, dest, Src
End Sub
See what happens when you iterate a lot, but copy very little (as the trick mostly speeds up the call by preventing VB to do it's regular "wise" checks, thus improving processing of string data for example). With a lot of data there is no difference as it already works close to the maximum speed available.
One thing I'm struck by is how incredibly slow doubles are. I always knew they were, but those giant bars really drive it home.
And as a corollary, how much faster singles are than doubles. Not much of a surprise that half the data size processes twice as fast, but again the big colored bars help with internalizing the concept.