C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

VBAのリスト問題4

こちらの続きです。
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個サイズを大きくする度に行っているので、
後半になればなるほど、コピーする量が多くなり遅くなる
のだと思っています。

・・・とは言え、コレクションより遥かに速い。