【テクニカル・上級編】【複数プロセス分散処理】フォルダ単位で別CScriptプロセスを起動し並列でテキスト検索を行う分割処理タスク – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

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待ち)の中に隠されている。

タイトルとURLをコピーしました