GUIの罠を排せ:THUMBSAVE制御によるDWG I/Oの極限最適化
エンジニアが「便利さ」という名の甘い罠に落ちたとき、システムのパフォーマンスは静かに、しかし確実に死へと向かう。
AutoCADにおける「サムネイルプレビュー」は、Windowsエクスプローラー上で図面の内容を視覚的に把握するための、ユーザーフレンドリーな機能だ。しかし、数千、数万の図面をネットワークストレージ(NAS/SAN)上で管理し、それをバッチ処理や自動化サーバーで回している実務の最前線において、この「親切心」は致命的なオーバーヘッドへと変貌する。
本稿では、システム変数`THUMBSAVE`を極限まで制御することで、DWGファイルのI/O負荷を最小化し、保存速度を劇的に向上させるためのアーキテクチャ的アプローチを詳解する。
1. 隠れたボトルネック:THUMBSAVEの正体
DWGファイル構造において、サムネイル画像はファイル末尾付近に埋め込まれるバイナリデータである。`THUMBSAVE`システム変数が`1`(デフォルト)に設定されている場合、`SAVE`コマンドを実行するたびに、AutoCADは現在のビューポートからビットマップを生成し、それをファイル構造内に書き込む。
一見、微々たる差に見えるだろう。しかし、以下の条件が重なったとき、その影響は指数関数的に増大する。
1. ネットワークレイテンシ: ファイルがローカルディスクではなく、SMB/NFS経由のネットワークストレージにある場合、追加のバイナリデータの転送はパケット数の増加を意味し、ネットワークのコンテンション(競合)を招く。
2. ファイルサイズの肥大化: 大規模な図面において、サムネイルが追加されるたびにファイルサイズが数MB単位で増加し続けるケースがある。これはストレージ容量を圧迫するだけでなく、バックアップや同期プロセスの負荷を増大させる。
3. バッチ処理の並列性: 数百の図面を自動処理する際、各プロセスがこの「不要な書き込み」を行うことで、ストレージのI/O待ち(I/O Wait)が発生し、全体の処理時間が大幅に遅延する。
我々が目指すべきは、「人間が見るための情報を、マシンが書くプロセスから切り離す」ことである。
2. 実装戦略:ステート管理を伴うセーフ・セーブ・パターン
単に`THUMBSAVE`を`0`に書き換えるだけでは、不完全な実装と言わざるを得ない。プロフェッショナルな自動化コードにおいては、「実行環境の整合性を維持すること」が絶対条件である。
つまり、処理中のみ設定を変更し、処理完了後には元のユーザー設定に確実に復元する「ステート管理」が必要不可欠となる。これを怠れば、自動化ツールを動かした後に、ユーザーが「エクスプローラーで図面が見えなくなった」とクレームを入れてくる事態を招く。
以下に、その極限のコード例を示す。
'==============================================================================
' Module: OptimizationModule
' Description: THUMBSAVEを制御し、I/O負荷を最小化した保存プロセスを実行する
'==============================================================================
Option Explicit
''' <summary>
''' サムネイル生成を無効化した状態で図面を高速保存する
''' </summary>
''' <param name="savePath">保存先のフルパス</param>
Public Sub OptimizedSave(ByVal savePath As String)
Dim originalThumbsave As Integer
Dim acadDoc As AcadDocument
Set acadDoc = ThisDrawing
On Error GoTo ErrorHandler
' 1. 現在のシステム変数の状態を退避(ステートの保存)
originalThumbsave = acadDoc.GetVariable("THUMBSAVE")
' 2. 高速化のためのチューニング
' THUMBSAVE = 0 : サムネイルを保存しない。これにより書き込みデータ量を削減。
acadDoc.SetVariable "THUMBSAVE", 0
' 必要に応じて他のシステム変数も調整(例: 画面更新の停止)
' acadDoc.SetVariable "REGENMODE", 0
Debug.Print "Optimization applied: THUMBSAVE set to 0"
' 3. 保存実行
' 注意: ネットワーク越しの保存時は、ファイルロックに注意が必要
acadDoc.SaveAs savePath
Debug.Print "Optimized save completed: " & savePath
CleanUp:
' 4. 環境の復元(ステートの復元)
' ユーザーの利便性を損なわないよう、必ず元の設定に戻す
On Error Resume Next
acadDoc.SetVariable "THUMBSAVE", originalThumbsave
Debug.Print "Environment restored: THUMBSAVE set to " & originalThumbsave
' オブジェクトの明示的な解放(メモリリーク防止)
Set acadDoc = Nothing
Exit Sub
ErrorHandler:
MsgBox "Critical Error during optimized save: " & Err.Description, vbCritical
Resume CleanUp
End Sub
3. さらに高みへ:I/O同期とWindows APIによる確実な制御
ネットワークストレージへの保存において、VBAの`SaveAs`が完了した直後に次の処理(ファイルの移動や削除、または別のプロセスによる読み込み)に移ろうとすると、「ファイルが別のプロセスによって使用されています」というエラーに遭遇することがある。
これは、OSレベルでの「遅延書き込み(Delayed Write)」や、ネットワークプロトコルによるファイルハンドルの解放遅延が原因だ。シニアエンジニアであれば、単なるエラーハンドリングに留まらず、I/Oの完了を物理的に待機するロジックを組み込むべきである。
ここでは、`FileSystemObject`によるリトライロジック、あるいはWindows APIを用いたファイル属性の監視を検討する。
'==============================================================================
' Advanced Technique: I/O Synchronization
'==============================================================================
''' <summary>
''' ファイルが完全に解放され、書き込み可能になるまで待機する
''' </summary>
Private Sub WaitForFileRelease(ByVal filePath As String, ByVal timeoutSeconds As Integer)
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim startTime As Double
startTime = Timer
Do While Timer < startTime + timeoutSeconds
On Error Resume Next
' ファイルを開こうとしてエラーが出なければ、ロックは解除されている
Dim ts As Object
Set ts = fso.OpenTextFile(filePath, 1) ' 読み取りモード
If Err.Number = 0 Then
ts.Close
Exit Do
End If
On Error GoTo 0
' CPU負荷を抑えるための微小待機
DoEvents
Sleep 100 ' Windows APIのSleepを使用することを推奨
Loop
End Sub
' ※ Sleep関数の宣言 (Standard Moduleの最上部に配置)
' Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
4. アーキテクチャの結論
図面保存の最適化は、単なる「設定変更」ではない。それは、「アプリケーションの挙動を、インフラの特性に合わせて再設計する」というエンジニアリングそのものである。
- ユーザー端末では、`THUMBSAVE = 1` を維持し、GUIの利便性を優先する。
- 自動化サーバー・バッチ処理では、`THUMBSAVE = 0` を強制し、I/Oスループットを極限まで引き上げる。
この使い分けを、コードレベルでのステート管理によって実装すること。これこそが、レガシーなCAD環境をモダンなデータパイプラインへと昇華させる、我々プロフェッショナルの流儀である。
現場に立つ者は、常に「その1バイトが、ネットワークの向こう側でどのようなコストを支払っているか」を意識せよ。
