VBScriptを再定義する:WSHマルチプロセス分散処理による高速検索アーキテクチャ
単一の`CScript.exe`で数百万のファイルを探索し、同期処理の限界に絶望したことはないか。VBScriptは遅いのではない。使い方が「シングルスレッド」という呪縛に囚われているだけだ。
今日は、Windowsのプロセス管理機構を逆手に取り、CPUコアをフル活用して巨大なファイルシステムを蹂躙する「並列分散サーチエンジン」の設計思想を伝授する。
—
1. なぜ「同期処理」が死に至る病なのか
VBScriptの実行エンジンである`WScript`は、本質的にシングルスレッドだ。巨大なフォルダツリーに対して`FileSystemObject`を再帰的に適用すれば、I/O待ちとCPUバウンドな解析で、最新のNVMe SSDであってもその性能の10%も引き出せない。
我々が目指すべきは、「親プロセス(オーケストレーター)」によるサブプロセスの動的生成と、結果の非同期集約である。
2. アーキテクチャの核心:分散処理の設計
今回のアーキテクチャは以下の3層で構成する。
1. Manager (Dispatcher): ルート直下のフォルダを列挙し、各フォルダを1つのタスクとして割り振る。
2. Worker (Executor): 引数で受け取った特定の階層のみを走査し、結果を一時ファイル(または標準出力)に書き出す。
3. Aggregator: 全Workerの完了を待ち、結果を統合する。
Workerスクリプト(Worker.vbs)
各プロセスは独立して動く。メモリリークを防ぐため、オブジェクトはスコープの終端で確実に`Nothing`化する。
‘ Worker.vbs – 特定フォルダを高速探索する単体プロセス
Option Explicit
Dim fso, folderPath, keyword, logFile
Set fso = CreateObject(“Scripting.FileSystemObject”)
folderPath = WScript.Arguments(0)
keyword = WScript.Arguments(1)
logFile = “result_” & Replace(fso.GetTempName, “.tmp”, “.txt”)
‘ 検索処理実行(再帰関数は最小限のメモリ消費に留める)
Call SearchFiles(fso.GetFolder(folderPath), keyword, logFile)
Set fso = Nothing
WScript.Quit 0
Sub SearchFiles(folder, target, logPath)
Dim file, subFolder, ts
Set ts = fso.OpenTextFile(logPath, 8, True) ‘ 追加書き込みモード
On Error Resume Next ‘ アクセス拒否フォルダを無視
For Each file In folder.Files
If InStr(file.Name, target) > 0 Then ts.WriteLine file.Path
Next
For Each subFolder In folder.SubFolders
Call SearchFiles(subFolder, target, logPath)
Next
On Error GoTo 0
ts.Close
Set ts = Nothing
End Sub
3. オーケストレーターの実装:WshShell.Runの魔術
親スクリプトは、`WshShell.Run`の第3引数`bWaitOnReturn`をあえて`False`に設定し、非同期でプロセスを乱射する。
‘ Orchestrator.vbs – 負荷分散の司令塔
Dim shell, fso, rootFolder, targetDir
Set shell = CreateObject(“WScript.Shell”)
Set fso = CreateObject(“Scripting.FileSystemObject”)
rootFolder = “C:\TargetData”
targetDir = fso.GetFolder(rootFolder)
‘ 各サブフォルダに対してCScriptプロセスを生成
For Each subFolder In targetDir.SubFolders
‘ 非同期で実行(並列化の鍵)
shell.Run “CScript //NoLogo Worker.vbs “”” & subFolder.Path & “”” “”target_keyword”””, 0, False
Next
‘ 注意: ここで全プロセスの完了を待つためのポーリング処理を実装する必要がある
‘ プロセスIDを管理し、WMI等で監視を行うのが「伝説級」のやり方だ。
4. 極限の知見:パフォーマンスと安定性のために
シニアエンジニアとして、以下の3点を遵守せよ。
- プロセスの最大数制御: 全てのサブフォルダに対してプロセスを投げると、OSのコンテキストスイッチが発生し、逆に遅延する。CPUコア数に合わせて`Semaphore`(排他制御)のようなキューイング処理を実装し、同時実行数を調整すること。
- メモリの解放: `Set obj = Nothing`は気休めではない。循環参照が疑われる場合、`Collect`の明示的な呼び出しは行えないが、オブジェクトの寿命を最小化することでガベージコレクションを促進させるのが鉄則だ。
- WMIによるプロセス監視: `Win32_Process`クラスを呼び出し、起動したプロセスの`TerminationDate`を監視することで、全処理の完了を正確に検知できる。`Sleep`で待つような素人仕事は禁止である。
結びに:レガシーは「遺物」ではなく「武器」である
VBScriptは、モダンな言語が隠蔽している「WindowsというOSそのものの肌触り」をダイレクトに操作できる。並列処理を実装することで、既存のレガシー資産は最新のストレージ性能をフルに引き出す「高速エンジン」へと昇華する。
スクリプトを単なるツールと呼ぶな。これは、OSという巨大な機械を制御するための、我々だけの「コマンドコード」なのだ。
現場で困ったら、またここへ来い。最適化のヒントは常に、システムが発する静かな悲鳴(I/O待ち)の中に隠されている。
