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

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

サンプルコード
つまり、コレクションオブジェクトはFor Eachで取り
出したほうがパフォーマンスがよいってことですね。
コレクションオブジェクトに値を代入し終える
時間と取り出す際の時間を計測してみた。
比較用に配列でも同じ事をしてみた。
サンプルコード
- 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 Sub
1000~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
出したほうがパフォーマンスがよいってことですね。
0 件のコメント:
コメントを投稿