「なんとなく遅い」から脱却せよ:StopwatchクラスでVB.NETのボトルネックを外科手術する
こんにちは。現場で「何となく重い」という言葉を耳にするたび、私はいつもこう思います。「計測なき改善は、目隠しをして迷路を走るようなものだ」と。
VB.NETを扱うエンジニアとして、次のステージへ進むための必須スキルが「定量的なパフォーマンス計測」です。今日は、プロフェッショナルが現場で日常的に使用している、`System.Diagnostics.Stopwatch`クラスを使ったプロファイリング手法を伝授します。
—
1. なぜ `DateTime.Now` ではいけないのか?
初学者の頃は、処理の開始時刻と終了時刻を `DateTime.Now` で取得して引き算をしがちです。しかし、これはプロの計測方法ではありません。
- 精度が粗い: `DateTime` はシステム時計に依存しており、ミリ秒未満の細かい計測には向きません。
- 環境の影響を受ける: OSが時刻同期(NTPなど)を行った瞬間に計測結果が狂う可能性があります。
対して `Stopwatch` クラスは、CPUの「高精度パフォーマンスカウンタ」を直接参照します。OSの時計調整の影響を受けず、ハードウェアレベルの正確な経過時間を取得できるのです。
—
2. 【実践】Stopwatchを使った計測の定石
まずは、最もシンプルな計測コードを見てみましょう。このパターンをテンプレートとして脳に焼き付けてください。
Imports System.Diagnostics
Public Sub MeasurePerformance()
‘ Stopwatchインスタンスを生成
Dim sw As New Stopwatch()
‘ 1. 計測開始
sw.Start()
‘ — 計測対象の処理(ここをプロファイリングします) —
Dim result As Long = 0
For i As Integer = 1 To 1000000
result += i
Next
‘ ————————————————–
‘ 2. 計測停止
sw.Stop()
‘ 3. 結果の出力(ミリ秒単位)
Console.WriteLine($”処理時間: {sw.ElapsedMilliseconds} ms”)
End Sub
ここがポイント:
- インスタンス化のタイミング: `New Stopwatch()` は計測の直前に行います。
- Stopメソッド: 処理が終わったら忘れずに `Stop()` を呼び出します。これを忘れると、後続の処理まで計測範囲に含まれてしまいます。
—
3. 「どこが重い?」を特定する外科手術的アプローチ
一つの大きなメソッド全体を計測しても、「どこが遅いのか」という犯人は見つかりません。プロは「区間計測」を行います。
Public Sub AdvancedProfiling()
Dim sw As New Stopwatch()
‘ 処理Aの計測
sw.Start()
‘ … データベース接続処理など …
sw.Stop()
Console.WriteLine($”DB接続時間: {sw.ElapsedMilliseconds} ms”)
‘ 累積計測の継続(リセットせずにRestartではなくStartを呼ぶ)
sw.Reset()
sw.Start()
‘ … 大量データのループ処理など …
sw.Stop()
Console.WriteLine($”データ処理時間: {sw.ElapsedMilliseconds} ms”)
End Sub
ボトルネック特定のための極意
1. 仮説を立てる: 「おそらくループ内のSQL発行が原因だろう」といった仮説を立てます。
2. 細分化する: 処理をステップごとに分割し、それぞれの区間を計測します。
3. 外れ値を捨てる: 初回実行時は、JITコンパイル(コードの最適化)の影響で遅くなることがあります。2回目以降の平均値を見るのがコツです。
—
4. 陥りやすい罠:パフォーマンス計測の注意点
初心者の方がよくやってしまう「計測の落とし穴」を3つだけ共有します。
- デバッグビルドで計測してはいけない:
Visual Studioの「Debug」モードは、開発を容易にするための余計な処理が含まれています。必ず「Release」モードでビルドして計測してください。パフォーマンスは数倍変わります。
- 計測自体が重い処理になっていないか:
超高速な処理(ナノ秒単位)を計測する場合、`Stopwatch` を呼び出すコスト自体が誤差を生みます。その場合は、10万回ループさせて合計時間を計り、それを回数で割る手法をとります。
- ガーベジコレクション(GC)の干渉:
計測中にGCが走ると、その分だけ処理時間が伸びます。極限まで精度を求めるなら、計測前に `GC.Collect()` を呼び出し、メモリをクリーンな状態にしてから開始するのも一つの手です。
—
最後に:計測は「愛」です
コードをただ書くのではなく、そのコードが走る時のCPUの鼓動を感じる。これがプロフェッショナルへの第一歩です。
「ここを直せば、ユーザーは0.5秒速く仕事ができるようになる」。そう考えて計測値を眺める時、あなたのVB.NETコードはただの文字列から、生きているプロダクトへと進化します。
さあ、まずは今のシステムの「重い場所」を一つ選んで、`Stopwatch` で暴いてみてください。その数値が、あなたのコードを最高傑作に変える手がかりになります。
ここをクリアすれば、もうあなたはただのコーダーではなく、「アプリケーションの設計士」です。応援していますよ!
