#13 ループ内ではコントロールを参照しない方がよい?

結論
コントロールのプロパティ値を参照するのは時間がかかるため、ループなどで何回も参照する必要がある場合にはあらかじめ変数にプロパティ値をセットし以降はその変数を参照するようにすべきである。

「#12 ループ内ではフィールドを参照しない方がよい?」ではテーブルやクエリーのフィールドをVBAで参照する場合のその方法と処理時間についてテストしてみましたが、ここではフォームやレポート上のコントロールのプロパティ値を参照する場合について、同様のテストを試みたいと思います。

ここでのテスト内容は次の3つです。実際のテストではテキストボックスコントロールの[Value]プロパティを参照しています。

  1. 毎回コントロールのプロパティを直接参照する。
  2. 最初に一度だけコントロールのプロパティを参照しその値を変数にセット、以降はその変数を参照する。
  3. あらかじめコントロールオブジェクト変数を宣言し、毎回そのオブジェクトを介してプロパティ値を参照する。
これらの3つのコードと実行結果の時間を次に示します。なお、テキストボックスコントロールの"txtData1"と"txtData2"にはそれぞれ"ABCDEFG"と"1234.567"があらかじめ入力されています。

  Dim txtData1 As TextBox, txtData2 As TextBox
  Dim strData1 As String, sngData2 As Single
  Dim strWrkData1 As String, strWrkData2 As String
  Dim sngWrkData1 As Single, sngWrkData2 As Single
  Dim iintLoop As Integer
    ---- 以上は1〜3共通 ----

  For iintLoop = 1 To 10000
    'コントロールのプロパティ値を各変数にセットする
    strWrkData1 = Me!txtData1.Value
    strWrkData2 = Me!txtData1.Value
    sngWrkData1 = Me!txtData2.Value
    sngWrkData2 = Me!txtData2.Value
  Next iintLoop
28.3秒
  'コントロールのプロパティ値を各変数にセット
  strData1 = Me!txtData1.Value
  sngData2 = Me!txtData2.Value
  For iintLoop = 1 To 10000
    'フィールド値の変数を各変数にセット
    strWrkData1 = strData1
    strWrkData2 = strData1
    sngWrkData1 = sngData2
    sngWrkData2 = sngData2
  Next iintLoop
0.06秒
  '各コントロールオブジェクトをセット
  Set txtData1 = Me!txtData1
  Set txtData2 = Me!txtData2
  For iintLoop = 1 To 10000
    'コントロールオブジェクトを各変数にセット
    strWrkData1 = txtData1.Value
    strWrkData2 = txtData1.Value
    sngWrkData1 = txtData2.Value
    sngWrkData2 = txtData2.Value
  Next iintLoop
0.47秒
※テキストボックスの値を取得する際に[Value]プロパティを明示的に記述していますが、 このプロパティはテキストボックスのデフォルトプロパティですので省略しても問題ありません。 また「#12 ループ内ではフィールドを参照しない方がよい?」の4番目のテストに対応するものは、ここではテスト2とほとんど同じなので割愛しました。


「#12 ループ内ではフィールドを参照しない方がよい?」のテストではテーブルを扱うということからディスクに対する物理的なアクセスも発生しているはずです。一方ここでのテストではフォーム上のコントロールを参照するだけですので、メモリ上のアクセスだけが発生し ているはずです。にも関わらず、テスト1の結果を見ると、レコードを1万件読み込んでフィールド値を変数に代入するのより、コントロールのプロパティ値を1万回変数に代入する方がはるかに(約10倍)時間がかかっています。コントロールを参照することがこれほど時間のかかるものとは思っても見ませんでした。とはいえ、最初に一度だけプロパティ値を変数にセットしてあとはその変数を参照するようにすれば、実に1/500ぐらいまで処理時間が短縮されることから、この手法の有効性がいかに高いかが分かります。

また、テーブルのフィールドを参照する場合では、Fieldオブジェクトを利用することがもっともよいと結論付けられましたが、コントロールの場合にはコントロールオブジェクトを使う方法は、確かに毎回毎回コントロールのプロパティを参照するよりははるかに速いですが、「もっとも速い方法ではない」のも特徴的な結果ではないでしょうか?。まとめると、「コントロールのプロパティ値を参照するのは時間がかかるため、ループなどで何回も参照する必要がある場合にはあらかじめ変数にプロパティ値をセットしそれ以降はその変数を参照するようにすべきである。」ということになります。

とはいえ、上記結果の時間値は1万回ものループを行った上での結果であることを忘れないで下さい。確かに差異は明らかですが、現実的にはそんなに多くの繰り返しを要するような処理はめったにないはずですから、全体的な時間としては非常に微々たるものと考えることもできるわけです。
| Index | Prev | Next |