#30 モジュールのコンパイルと実行速度の関係

結論
モジュールのコンパイルの有無による実行速度に対する影響はほとんどない。コンパイルはコードの文法等の事前エラーチェック機能程度と考えられる。

一般的に「コンパイル」というと、人間に認識できるテキスト形式のソースコードを、中間形式のオブジェクトファイルに変換するという処理を指します。そして、その後「リンク」という処理を行い、EXE形式のファイルを生成するというのがコンパイラ言語の開発作業の流れになります(VBやDelphiなどの開発環境ではそれらを意識することなく、”実行”することによって一連の処理が行われますが)。しかし、Accessのモジュールでいうところのコンパイルは、それとは内容が異なっているようです。コンパイルを行ったからといって、エクスプローラで見られるような何らかのファイルが生成されるわけでもなく、またコンパイルをしないでもプログラムはそのまま走ってしまいます。つまり、開発者はコンパイルという作業手順をまったく意識しなくても済んでしまうのです。

それでは、いったいなぜVBEのメニューやツールバーに「コンパイル」という処理が付いているのでしょうか?。1つの大きな目的としては、コードを実行する前にコンパイルを行うことによって、すべてのモジュールについてエラーチェックができるという点が挙げられます。文法的な構文エラーはもとより、VBAが提供していない関数(綴りの間違いも含めて)を呼び出していたり、モジュール上に存在しないプロシージャを呼び出していたり、あるいはAccessではよくあることですが、ADOの参照設定しかしていないのに、コードでDAOを使っていたり、そういったチェックを事前に行ってくれます。特に、その利用価値が高いと思うのは、あるプロシージャだけでなく、フォームのクラスモジュールや標準モジュールなど、すべてのモジュールに渡ってそのチェックをしてくれるという点です。例えば、フォームに"終了"という名前のコマンドボタンがあり、その"クリック時"イベントプロシージャがコーディングしてあるとします。コンパイルせずにフォームを実行し、そのボタンをクリックした場合、その"クリック時"イベントプロシージャ内にエラーがなければ、Accessはそれを正常に実行し、何もエラーを通知してくれません。まったく他のモジュールに明らかな文法エラーがあったとしてもです。そして、そのエラーのあるモジュールが実行されたときはじめてエラーを通知してくれるのです。このような状況でも、事前にコンパイルを実行しておけば、他のモジュールについても同時にエラーチェックをしてくれる、これはデバッグ上、非常に大切なことだと思います。


さて、DOSの頃からプログラミングを行っている個人的なイメージとしては、ソースコードをコンパイルせずに1行ずつ解釈しながら実行する「インタプリタ言語」は実行速度が遅く、「コンパイラ言語」はそれよりも実行速度が速い、という固定概念を持っているのですが、Accessが提供しているような「コンパイル」は実行速度の面ではどうなのでしょうか?。"パフォーマンスを研究する"というこのAccess Laboのテーマに沿って、ここではその点について比較を行ってみることにしましょう。


まず、テスト用として、次のようなコードを標準モジュールに作成してみました。

特に具体的な処理をしているというものではなく、単純に、テーブル「入出庫明細」の全レコードをループで繰り返し読み込み、さらに単純な演算をひたすらループで繰り返すというだけのものです。処理の開始時には、現在の午前0時からの経過時間をTimer関数で取得し、ループ処理が終わったところで、その時点のTimer関数値を調べ、2つのループ処理全体の経過時間=処理時間をイミディエイトウィンドウに出力しています。


Sub test()

  Dim dbs As Database
  Dim rst As Recordset
  Dim dblCurTimer As Double
  Dim dblResult As Double
  Dim ilngLoop As Long

  dblCurTimer = Timer

  'ひたすらレコード移動を行う
  Set dbs = CurrentDb
  Set rst = dbs.OpenRecordset("入出庫明細")
  With rst
    For ilngLoop = 1 To 500
      Do Until .EOF
        .MoveNext
      Loop
      .MoveFirst
    Next ilngLoop
    .Close
  End With

  'ひたすら数値演算を行う
  For ilngLoop = 1 To 5000000
    dblResult = (Sqr(2) + Sqr(3)) / Sqr(4)
    dblResult = 0.12345 / 2 * 9.87654
  Next ilngLoop
  
  Debug.Print "コンパイルあり-テスト結果: " & _
              Format$(Timer - dblCurTimer, "0.000")

End Sub



さて、Access VBEのツールバーのコンパイルボタンを見れば分かるように、一度コンパイルを実行すると、すでに"コンパイル済み"ということで、そのボタンは使用不可になります。そして、コードのいずれかを編集すると、"未コンパイル"ということになり、ボタンが使用可能に替わります。そこで今回は、コードの下の方にある「コンパイルあり-テスト結果: 」の部分を、「コンパイルあり」・「コンパイルなし」というように、交互に書き換えながら実行することによってテストを進めていくことにします。つまり、まずこの部分のコードを「コンパイルなし」に書き換えて、コンパイルせずに直ちに実行します。これがコンパイルなしの実行結果となります。続いて、「コンパイルあり」に書き換えて、コンパイルを実行、続いてプロシージャを実行します。これがコンパイルありの実行結果となります。


テスト結果は次のようになりました。個々の結果を見てみると、コンパイル有り無しで常に明らかな差が出ているわけではありませんでした。時にはコンパイルありの方が速く、時には遅いこともあったのです。したがって、下表ではそれぞれの結果を昇順に並べ替え、平均値で結果を比較してみることにしました。
コンパイル有無 実行時間 合計時間 平均時間
あり 10.929 98.687 10.965
10.930
10.931
10.978
10.979
10.980
10.982
10.988
10.990
なし 10.930 98.826 10.981
10.930
10.980
10.980
10.990
10.991
10.991
10.992
11.042
ご覧のように、平均値で見ると、コンパイルありの方が本当にちょっとだけの時間ですが、速く処理が行われていることが分かります。ところがそれは、10秒強の処理全体に比べればほとんど無視できる程度の時間差です。しかも、もっとも速い時は10.929と10.930で、両者にまったく違いがないのです。このことから、「コンパイルの有無はパフォーマンスに影響を与えない」と断言してもよいのではないでしょうか?。Accessの特徴として、コンパイルしないで実行すると、ツールバーのコンパイルボタンが使用不可になります。おそらく実行とともに部分的なコンパイルが行われるためかもしれません。その瞬間的な時間だけが上記の差として現れていると考えられます。

結論として、Accessの「コンパイル」というものは、パフォーマンスには影響はなく、プログラム実行前の事前のエラーチェック機能程度として考えてよさそうです。
| Index | Prev | Next |

 

Copyright © T'sWare All rights reserved