こちらの続きです。
VBAのリスト問題3 - C#ATIA
進みが悪い・・・。
続いて動的配列です。
Long型だけで比べるとこんな感じです。
**可変長配列** Long 代入:0.0234375s 呼出:0.0234375s **可変長配列 Preserve** Long 代入:0.9375s 呼出:0.0234375s
呼び出しは誤差程度なのですが、代入には差があります。
まぁ当然だとは思います。
代入だけをこの様な感じで再度テストします。
'vba Option Explicit Private sw_ As StopWatch Sub ReDim_Preserve_test() Dim count As Long count = 1000000 '一度で Set sw_ = New StopWatch sw_.start Debug.Print "-- 一度で --" Call preserve_once(count) Call sw_.total("Total" & ":") '毎回 Set sw_ = New StopWatch sw_.start Debug.Print "-- 毎回 --" Call preserve_every_time(count) Call sw_.total("Total" & ":") End Sub Private Sub preserve_every_time( _ ByVal count As Long) Dim ary() As Long Dim i As Long For i = 0 To count - 1 ReDim Preserve ary(i) ary(i) = i If i Mod 100000 = 0 Then Call sw_.split(CStr(i) & ":") End If Next End Sub Private Sub preserve_once( _ ByVal count As Long) Dim ary() As Long ReDim ary(count) Dim i As Long For i = 0 To count - 1 ary(i) = i If i Mod 100000 = 0 Then Call sw_.split(CStr(i) & ":") End If Next End Sub
結果を見やすくするとこんな感じです。
最初に必要なサイズを確保した場合、書き出す意味が無いぐらい
速いですね・・・。
そこが目的では無く、毎回ReDim Preserveしている方は、
後半に向けて徐々に遅くなっています。
これは理由を知ってます。
配列の場合、メモリはコレクションの時と異なり連続した状態で確保されます。
その為、配列要素の1個のサイズが確定すれば、100個先だろうが1万個先だろうが
どこに目的の要素があるかが分かっている為、呼び出しも高速です。
ReDim Preserveが徐々に遅くなる原因は、こんな理由でしょう。
サイズが5個から6個になる場合、6個目は5個目の隣のメモリを確保する
訳ではないです。
まず、6個分のメモリを確保します。これがReDim。
続いて元の5個分の内容をコピーする。これがPreserve。
これを1個サイズを大きくする度に行っているので、
後半になればなるほど、コピーする量が多くなり遅くなる
のだと思っています。
・・・とは言え、コレクションより遥かに速い。