こんにちは! VBScriptの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、自分の手でWindowsを意のままにコントロールしたい。そんな熱量を持ったあなたを、私は心から歓迎します。
さて、業務自動化を進めていくと、こんな壁にぶつかりませんか?
「なんだかこのスクリプト、動き出すまでにやたら時間がかかるぞ…?」
「大量のファイルを処理しているけど、どこが一番時間を食っているんだ?」
感覚だけで「遅い」と嘆くのは、プロフェッショナルなエンジニアのやり方ではありません。今日は、VBScriptの実行時間をミリ秒単位で正確に測り、コードの「ボトルネック(足かせ)」を外科手術のメスのように特定する【高速プロファイリング】の極意を伝授します。
ここをクリアすれば、あなたの書くスクリプトは見違えるほど洗練されますよ。さあ、一緒に本質を学んでいきましょう!
—
1. なぜ「感覚」ではなく「計測」が必要なのか?
VBScriptは、OSに標準搭載されているWindows Script Host(WSH)上で動く、非常に軽快で素晴らしい言語です。しかし、COMオブジェクト(ExcelやFileSystemObjectなど)の呼び出し方ひとつで、パフォーマンスが何倍にも跳ね上がります。
人間は、数秒の遅延に対して非常に鈍感です。「あれ、固まったかな?」と思ったとき、裏では何十ミリ秒、あるいは何秒もの無駄な時間が流れています。
コードのどこが遅いのかを客観的な「数字」で捉えること。これが、チーフアーキテクトへの第一歩です。
—
2. 計測の二大巨頭:`Timer` 関数と `GetTickCount` API
VBScriptで時間を測る代表的な方法には、次の2つがあります。
1. `Timer` 関数(お手軽・標準)
- 午前0時からの経過時間を秒単位(小数点以下も含む)で返します。
- スクリプト全体の簡易的な計測に向いています。
2. `GetTickCount` (高精度・WSHの隠し味)
- Windowsが起動してからのミリ秒数を返すWindows APIです。
- 非常に高速なループ処理などの細かい計測に向いています。
今回は、より実践的でミリ秒単位の細かい測定が可能な「カスタム・プロファイラクラス(関数群)」の形にして、あなたにプレゼントしましょう。
—
3. 実践! ボトルネック特定プロファイラの実装
以下のコードをメモ帳に貼り付けて、拡張子を `.vbs` (例:`profiler_sample.vbs`)にして保存してみてください。デスクトップでダブルクリックするだけで、その性能を体感できます。
‘ =================================================================0
‘ タイトル: VBScript 高速プロファイリング実践スクリプト
‘ 概要: 処理の経過時間を計測し、ボトルネックを可視化する手法
‘ =================================================================0
Option Explicit
‘ 1. スクリプト全体の開始時間を記録(タイマー始動)
Dim dblStartTime
dblStartTime = Timer
WScript.Echo “=== プロファイリングを開始します ===”
‘ —————————————————————–
‘ 【検証A】文字列結合のパフォーマンス(不適切な例 vs 適切な例)
‘ —————————————————————–
Dim t1, t2
t1 = Timer
‘ ボトルネックになりやすい例:ループ内で文字列を `&` で結合し続ける
‘ (VBScriptではメモリ再割り当てが発生し、後半になるにつれて急激に遅くなります)
Dim i, slowStr
slowStr = “”
For i = 1 to 5000
slowStr = slowStr & “A”
Next
t2 = Timer
WScript.Echo “検証A(&による文字列結合 5000回): ” & FormatNumber((t2 – t1) 1000, 2) & ” ミリ秒”
‘ —————————————————————–
‘ 【検証B】Array(配列)を使った高速化手法
‘ —————————————————————–
t1 = Timer
‘ 改善例:Arrayに溜め込んでから Join する(劇的に速いです)
Dim arr(5000)
For i = 0 to 4999
arr(i) = “A”
Next
Dim fastStr
fastStr = Join(arr, “”)
t2 = Timer
WScript.Echo “検証B(Array + Join 5000回): ” & FormatNumber((t2 – t1) 1000, 2) & ” ミリ秒”
‘ —————————————————————–
‘ 3. トータル集計
‘ —————————————————————–
Dim dblTotalTime
dblTotalTime = (Timer – dblStartTime) 1000
WScript.Echo “————————————————–”
WScript.Echo “全処理完了! 総実行時間: ” & FormatNumber(dblTotalTime, 2) & ” ミリ秒”
WScript.Echo “=== プロファイリング終了 ===”
—
4. コードの解説:ここがエンジニアの急所!
初心者の方が陥りがちなポイントと、コードの重要な意味を紐解いていきましょう。
① `Option Explicit` はプロの証
スクリプトの1行目に書いてある `Option Explicit`。「変数の宣言を強制する」というお約束です。これを書くことで、うっかりミスによるタイポ(変数名の打ち間違い)を未然に防ぎ、メモリの無駄遣いを防ぐクリーンなコードが書けるようになります。絶対に省略しないでくださいね。
② `Timer` 関数のミリ秒換算
`Timer` は「秒」を返します。人間にとって馴染み深い「ミリ秒(1/1000秒)」にするために、`(t2 – t1) 1000` という計算をしています。さらに `FormatNumber(…, 2)` で小数第2位までに丸めることで、ログが非常に見やすくなります。
③ なぜ文字列の結合(検証A vs 検証B)でここまで差が出るのか?
これが今日の最大の学びです。
VBScriptにおいて、ループの中で `str = str & “A”` とやると、OSは「毎回メモリを確保し直し、古いデータをコピーし、新しいデータを追加する」という重い処理を裏でこっそり行います。これが「メモリ再割り当てのオーバーヘッド」です。
一方、検証Bのようにあらかじめメモリの箱(配列)を用意し、最後に `Join` で一気に繋げば、OSの負担は最小限で済みます。
プロファイリングを行うと、「どの書き方がボトルネックを生んでいるか」が数字として残酷なまでに浮き彫りになるのです。
—
5. 現場で使える!陥りやすいエラーと回避の知恵
1. 「0.00ミリ秒」と表示されて計測できない場合
処理が軽すぎて、`Timer` 関数の分解能(Windowsのタイマー精度)を下回ると 0 ミリ秒と表示されます。その場合は、ループ回数を10倍に増やすなどして、計測可能な規模にスケールさせてください。
2. 外部COMオブジェクト(Excel等)を絡めるときの一言
Excel操作の自動化で遅いと感じる場合、大半の原因は「VBScriptとExcelの間の通信回数(往復回数)」です。セルに1つずつ値を書き込むのではなく、2次元配列にデータを一気に格納してから、`.Value = データの配列` と一撃で書き込むのが、爆速化の鉄則ですよ。
—
まとめ
いかがでしたか?
今回は `Timer` 関数を用いて、コードのどこが遅いのかを数値化する「プロファイリング」の手法を解説しました。
- 感覚でコードを直さず、必ず計測(プロファイリング)する
- ボトルネックになりやすい箇所(文字列結合やループ内のCOM操作)を疑う
- アルゴリズムを工夫してオーバーヘッドを削る
ここをクリアすれば、あなたはもうただの「スクリプトの利用者」ではありません。システムの挙動を支配する「エンジニア」です。
日々の自動化スクリプトにこの視点を取り入れて、周囲をアッと言わせる高速なプログラムを書いてみてくださいね。それでは、次のステップでお会いしましょう!
