結論:コレクションオブジェクトからループで値を取り出す際にFor文を使ってはいけない。
コレクションオブジェクトに値を代入し終える
時間と取り出す際の時間を計測してみた。
比較用に配列でも同じ事をしてみた。
サンプルコード
1000~5万データで各データ10回テストした平均の時間を記載してあります。
単位は[ms]です。

たった1回でもコレクションオブジェクトに対しインデックスを
使って値を取り出しただけでこれほどの時間がかかるわけです。
例えば、1つのループ内で3回、インデックス経由で呼出を行うと
3倍時間がかかるわけです。
ただし、問題はコレクションオブジェクトに対し、インデックスを利用して
値を取り出すことにあって、キー経由で取り出す分には影響がないということです。
上記コードで、コレクションオブジェクトの値を取り出す部分を
For文からFor Each文に切り替えると以下の通りになります。
単位は[ms]です。

サンプルコード
出したほうがパフォーマンスがよいってことですね。
コレクションオブジェクトに値を代入し終える
時間と取り出す際の時間を計測してみた。
比較用に配列でも同じ事をしてみた。
サンプルコード
Option Explicit
Declare Function GetTickCount Lib "kernel32" () As Long
Sub SampleCode()
Dim Temp As Long
Dim BaseTime As Double, i As Long
Dim MaxNumber As Long: MaxNumber = 1000
Dim VarCollection As New Collection
Dim VarArray() As Long
'■コレクションオブジェクトに値を格納する
BaseTime = GetTickCount
For i = 0 To MaxNumber
VarCollection.Add i
Next
Debug.Print "Collection[In] :" & GetTickCount - BaseTime
BaseTime = GetTickCount
For i = 1 To MaxNumber + 1
Temp = VarCollection.Item(i)
Next
Debug.Print "Collection[In] :" & GetTickCount - BaseTime
'■配列に値を格納する
BaseTime = GetTickCount
For i = 0 To MaxNumber
ReDim Preserve VarArray(i)
VarArray(i) = i
Next
Debug.Print "Collection[In] :" & GetTickCount - BaseTime
BaseTime = GetTickCount
For i = 0 To MaxNumber
Temp = VarArray(i)
Temp = VarArray(i)
Next
Debug.Print "Collection[In] :" & GetTickCount - BaseTime
End Sub1000~5万データで各データ10回テストした平均の時間を記載してあります。
単位は[ms]です。

たった1回でもコレクションオブジェクトに対しインデックスを
使って値を取り出しただけでこれほどの時間がかかるわけです。
例えば、1つのループ内で3回、インデックス経由で呼出を行うと
3倍時間がかかるわけです。
ただし、問題はコレクションオブジェクトに対し、インデックスを利用して
値を取り出すことにあって、キー経由で取り出す分には影響がないということです。
上記コードで、コレクションオブジェクトの値を取り出す部分を
For文からFor Each文に切り替えると以下の通りになります。
単位は[ms]です。

サンプルコード
Option Explicit
Declare Function GetTickCount Lib "kernel32" () As Long
Sub SampleCode2()
Dim Temp As Long
Dim BaseTime As Double, i As Long, v As Variant
Dim MaxNumber As Long: MaxNumber = 50000
Dim VarCollection As New Collection
'■コレクションオブジェクトに値を格納する
BaseTime = GetTickCount
For i = 0 To MaxNumber
VarCollection.Add i
Next
Debug.Print "Collection[In] :" & GetTickCount - BaseTime
BaseTime = GetTickCount
For Each v In VarCollection
Temp = v
Next
Debug.Print "Collection[Out]:" & GetTickCount - BaseTime
End Subつまり、コレクションオブジェクトはFor Eachで取り出したほうがパフォーマンスがよいってことですね。
0 件のコメント:
コメントを投稿