今回は「VB6.0やVBAだとこういう書き方もアリなんだー」という、個人的には目から鱗ネタです。下記のソース、(1)と(2)、どちらが速いか?というわけですね。
(1)- For i = 0 To lngMax
- strText1 = strText1 & "あいうえおかきくけこさしすせそ"
- Next
- For i = 0 To lngMax
- strText2 = strText2 & "あいうえおかきくけこさしすせそ"
- If Len(strText2) > 3000 Then strText1 = strText1 & strText2: strText2 = vbNullString
- Next
- If Len(strText2) Then strText1 = strText1 & strText2
(1)の方が一般的な書き方だと思いますが、この場合、(2)の方が圧倒的に速いのです。
結果
(1):343 ミリ秒
(2):16 ミリ秒
※Acceess2003で実験
VB6.0のString型は値型なので文字列を追加する度に、データの文字列をコピーしているわけですね。コピーするものが、長ければ長いほど、コピーの作業にコストがかかる。
ひるがえって(2)ではstrText2にちまちま文字列を追加して、
If Len(strText2) > 3000
のタイミングでstrText1に突っ込んで、strText2をカラッポにしてまた文字列をためていく。その方が、長い文字列をコピーする回数が激減して、処理が速くなるというわけなんですね(ちなみに.Netだとstring型は一応参照型なので、文字列をセットする度にコンストラクタが発生している様子でVB6.0/VBAどころではない負荷を、もはや「体感」として感じます。なのでStringBuilderのインデクサで対応)。
サンプルソース
フォームにtxtDATAという名前のテキストボックスを作って、そこにタイムを表示する。clsTimerMMクラスは「時間経過計測クラス‐VBA編」参照。
- Dim clsTimerMM As clsTimerMM
- Dim strTextMsg As String
- '************************
- Dim strMsg As String
- Dim strText1 As String
- Dim strText2 As String
- Dim lngMax As Long
- Dim i As Long
- '************************
- Set clsTimerMM = New clsTimerMM
- strMsg = "あいうえおかきくけこさしすせそ"
- lngMax = 10000
- '************************
- clsTimerMM.SetStartDate
- For i = 0 To lngMax
- strText1 = strText1 & strMsg
- Next
- strTextMsg = "(1):" & clsTimerMM.ElapsedTime & vbCrLf
- Me.txtText1.Value = strText1 & vbCrLf
- strText1 = vbNullString
- '************************
- clsTimerMM.SetStartDate
- For i = 0 To lngMax
- strText2 = strText2 & strMsg
- If Len(strText2) > 3000 Then strText1 = strText1 & strText2: strText2 = vbNullString
- Next
- If Len(strText2) Then strText1 = strText1 & strText2
- strTextMsg = strTextMsg & "(2):" & clsTimerMM.ElapsedTime & vbCrLf
- Me.txtText2.Value = strText1 & vbCrLf
- Me.txtDATA.Value = strTextMsg
- Set clsTimerMM = Nothing
0 件のコメント:
コメントを投稿