VBScriptを再定義する:Scripting.Dictionaryによる「O(n)」の高速データ処理術
レガシーシステムの保守や、RPAが介在する自動化の現場において、未だVBScriptは現役だ。しかし、多くのエンジニアが「VBScriptは遅い」という先入観のもと、二重ループでデータを突き合わせるような非効率極まりないコードを量産している。
いいか、VBScriptの真髄は「COMオブジェクトをいかにメモリ上で効率的にハンドリングするか」にある。今回は、数万件規模のログ解析を一瞬で完結させる『Scripting.Dictionary』を用いたO(n)アルゴリズムの真髄を伝授する。
—
1. なぜ「Dictionary」が最強の武器なのか
配列を二重ループ(`For`の中に`For`)で回せば、計算量はO(n²)となる。データが1万件あれば、最大1億回の比較が発生する。これが「VBScriptは遅い」と言われる最大の原因だ。
`Scripting.Dictionary`は、内部的にハッシュテーブルを実装している。キーによるアクセスは理論上O(1)だ。つまり、データ件数が線形に増えても、処理時間は正比例でしか増えない。この差は、システム稼働時間において致命的な差を生む。
—
2. 高速重複排除の実装コード
以下のコードは、数万行のログファイルから「ユニークなユーザーID」を抽出し、それぞれの発生回数を集計する例だ。
‘ 高速データ集計エンジンの核心
Function AggregateLogData(arrData)
Dim dict, item, key
‘ Late Bindingでインスタンス化(パフォーマンスを考慮し適宜Early Bindingも検討)
Set dict = CreateObject(“Scripting.Dictionary”)
‘ メモリ最適化: CompareModeを設定し、大文字小文字を区別(vbBinaryCompare)または無視(vbTextCompare)
‘ デフォルトはバイナリ比較。仕様に合わせて明示的に設定せよ
dict.CompareMode = 1
‘ O(n)のループ処理: ここがボトルネック解消の鍵
For Each item In arrData
If Not dict.Exists(item) Then
dict.Add item, 1
Else
dict(item) = dict(item) + 1
End If
Next
Set AggregateLogData = dict
End Function
—
3. シニアエンジニアが意識すべき「メモリの流儀」
VBScriptはガベージコレクションを備えていない。COMオブジェクトのライフサイクル管理を疎かにすることは、メモリリークという名の「時限爆弾」を仕掛けることと同義だ。
オブジェクトの明示的解放(Destruction)
`Set dict = Nothing` を忘れるな。特に、WSHで長時間常駐するバックグラウンドプロセスにおいては、スコープを抜ける前に必ず参照を断ち切る必要がある。
Sub ProcessMaster()
Dim oDict
Set oDict = AggregateLogData(sourceArray)
‘ 処理実行…
‘ スコープ終了直前に明示的解放
Set oDict = Nothing
End Sub
—
4. 極限のチューニング:Windows APIとの連携
さらに処理を高速化したい場合や、ファイルシステムへのI/Oを最適化したい場合、`Scripting.FileSystemObject`(FSO)に頼りすぎないことも重要だ。
- ADODB.Streamの活用: FSOの`ReadAll`は巨大なログファイルに対してはメモリを食い尽くす。`ADODB.Stream`でバイナリとして読み込み、バッファリング制御を行うことで、メモリ効率を劇的に改善できる。
- Dictionaryの限界を知る: 100万件を超えるデータセットを扱うなら、VBScriptの限界は近い。その際はSQLite(`System.Data.SQLite`)や、外部の高速なコマンドラインツール(`grep`や`awk`のWindows移植版)を呼び出し、VBScriptは「オーケストレーター」に徹するべきだ。
—
5. アーキテクトからの提言
VBScriptは「終わった技術」ではない。「OSの深部にまで届く、軽量なランタイム」として再評価すべきだ。
エンジニアとして恥ずべきは、技術の古さではなく、その技術のポテンシャルを最大限に引き出せず、計算量を無視したアルゴリズムでシステムを重くすることだ。今日紹介したDictionaryによるハッシュ管理は、その第一歩に過ぎない。
次にあなたがコードを書くとき、そのループは本当に必要なのか? 二重ループを書こうとしている指を止め、Scripting.DictionaryでO(n)に変換できるかを一度だけ自問自答してほしい。それが、プロフェッショナルの矜持だ。
