나는 Tim Williams의 충고를 따르고 몇 가지 속도 테스트를 수행했습니다.
컬렉션/배열의 각 유형에 대해 먼저 클래스 "SpeedTester"의 객체를 추가했습니다.이 객체는 get/set 속성을 사용하여 긴 변수가있는 쉘 객체였습니다. 변수의 값은 루프 인덱스 (1에서 100,000 사이)의 값입니다.
그런 다음 컬렉션/배열의 각 개체에 액세스하고 개체의 긴 속성 값을 새 변수에 할당하는 두 번째 루프를 수행했습니다. long 타입. 나는 방법 당 3 라운드를 수행하고, And와 get 루프의 시간을 평균했다.
결과는 다음과 같다 :
Method Avg Add Time Avg Get Time Total Time
Collection Indexed 0.305 25.498 25.803
Collection Mapped 1.021 0.320 1.342
Collection Indexed For Each 0.334 0.033 0.367
Collection Mapped For Each 1.084 0.039 1.123
Dynamic Array Typed 0.303 0.039 0.342
Static Array Typed 0.251 0.016 0.266
방법 컬렉션 인덱스 및 매핑 컬렉션 컬렉션의 개체를 유지하고있었습니다. 첫 번째 키에 키가 추가되지 않았고 두 번째 키에 객체의 긴 속성이 문자열로 변환 된 키가 추가되었습니다. 그런 다음 이러한 개체는 1에서 c.Count의 인덱스를 사용하여 for 루프에서 액세스되었습니다 .Count
다음 두 메서드는 변수가 컬렉션에 추가되는 방식에서 처음 두 메서드와 동일합니다. 그러나 Get 루프의 경우 for 루프를 인덱스와 함께 사용하는 대신 for-each 루프를 사용했습니다.
동적 배열 형식은 SpeedTester 형식의 배열을 포함하는 사용자 지정 클래스입니다. 변수가 추가 될 때마다 배열의 크기가 1 슬롯만큼 확장되었습니다 (ReDim Preserve 사용). get-loop는 일반적으로 배열 에서처럼 1에서 100,000까지의 인덱스를 사용하는 for-loop였습니다.
마지막으로 정적 배열 형식은 단순히 SpeedTester 유형의 배열이며 100,000 개의 슬롯으로 초기화되었습니다. 분명히 이것은 가장 빠른 방법입니다. 이상하게도 속도 향상의 상당 부분은 추가가 아닌 얻기에있었습니다.각 개체를 가져 오는 것이 동적 배열보다 빠르지 만 크기를 조정할 필요가 있기 때문에 추가하는 것이 다른 메서드에서는 더 느릴 것이라고 생각했을 것입니다.
인덱스 된 컬렉션의 개체에 액세스하기 위해 for 루프와 for 루프를 사용하는 것의 차이점에 놀랐습니다. 매핑 된 컬렉션의 주요 조회 속도가 놀랍습니다. 인덱싱보다 훨씬 빠르고 정적 배열을 제외한 다른 모든 메서드와 비슷합니다.
간단히 말해서, 그것들은 내 프로젝트에 대한 모든 실행 가능한 대안입니다 (첫 번째와 마지막 방법을 제외하고, 처음에는 속도가 느리기 때문에 마지막으로 동적으로 크기 조정 가능한 배열이 필요하기 때문입니다). 컬렉션이 실제로 구현되는 방법이나 동적 배열과 정적 배열 간의 구현 차이에 대해서는 전혀 알지 못합니다. 더 이상의 통찰력을 많이 주시면 감사하겠습니다.
EDIT : (동적 배열을 사용하여) 시험 자체 코드
Public Sub TestSpeed()
Dim ts As Double
ts = Timer()
Dim c As TesterList
Set c = New TesterList
Dim aTester As SpeedTester
Dim i As Long
For i = 1 To 100000
Set aTester = New SpeedTester
aTester.Number = i
Call c.Add(aTester)
Next i
Dim taa As Double
taa = Timer()
For i = c.FirstIndex To c.LastIndex
Set aTester = c.Item(i)
Dim n As Long
n = aTester.Number
Next i
Dim tag As Double
tag = Timer()
MsgBox "Time to add: " & (taa - ts) & vbNewLine & "Time to get: " & (tag - taa)
End Sub
그리고 동적 배열 클래스 TesterList위한
:
Private fTesters() As SpeedTester
Public Property Get FirstIndex() As Long
On Error GoTo Leave
FirstIndex = LBound(fTesters)
Leave:
On Error GoTo 0
End Property
Public Property Get LastIndex() As Long
On Error GoTo Leave
LastIndex = UBound(fTesters)
Leave:
On Error GoTo 0
End Property
Public Sub Add(pTester As SpeedTester)
On Error Resume Next
ReDim Preserve fTesters(1 To UBound(fTesters) + 1) As SpeedTester
If Err.Number <> 0 Then
ReDim fTesters(1 To 1) As SpeedTester
End If
Set fTesters(UBound(fTesters)) = pTester
On Error GoTo 0
End Sub
Public Function Item(i As Long) As SpeedTester
On Error GoTo Leave
Set Item = fTesters(i)
Leave:
On Error GoTo 0
End Function
그리고 마지막으로, 매우 간단한 SpeedTester 객체 클래스 :
Private fNumber As Long
Public Property Get Number() As Long
Number = fNumber
End Property
Public Property Let Number(pNumber As Long)
fNumber = pNumber
End Property
얼마나 자주 크기를 조정합니까? VBA는 이것이 자주 발생하지 않거나 새 배열의 크기를 알 수 있고 배열 (콜렉션이 아닌)을 계속 사용할 수있게하면 'redim preserve'를 통해 동적 배열 크기 조정을 허용합니다. – enderland
차이가 중요한지 여부는 정확한 사용 사례에 따라 다를 수 있습니다. 그래도 테스트하는 것이 매우 쉬울 것 같습니다 : 어떤 비교를 해 보았습니까? –