CPUの使用率を抑える方法


何か、すごく時間のかかるループを実行すると、処理が終わるまでCPUの使用率が100%近くになることがあります。

Sub Sample1()
    Dim buf As String
    Const LogFile As String = "C:\log\ex090310.log"
    Open LogFile For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            Debug.Print buf
        Loop
    Close #1
End Sub

上記の"C:\log\ex090310.log"は、サーバーのログファイルです。テキストファイルで約45MB、約20万行あります。さすがに、このボリュームになると、Line Inputで1行ずつ読むのには時間がかかります。そして、処理が終わるまで、CPUの使用率はずっと100%となります。

マクロが終わるまで、コーヒーでも飲んでいられればいいのですが、その間に別の仕事をしたいときには困ります。VBAがCPUを独占しているので、エディタで原稿を書こうとしても、いつものような快適さは望めません。

VBAのDoEvents関数を使ってはどうでしょう。DoEvents関数は、ヘルプによると「プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数」だそうです。確かに、こうした長い時間がかかるマクロを、ユーザーが途中で停止できるような仕組みでは必須ですが、CPUの使用率を抑える効果は期待できません。

Sub Sample1()
    Dim buf As String
    Const LogFile As String = "C:\log\ex090310.log"
    Open LogFile For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            Debug.Print buf
            DoEvents
        Loop
    Close #1
End Sub

こんなときは、Windows APIのSleepを使うと、CPUの使用率を抑えられます。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub Sample1()
    Dim buf As String
    Const LogFile As String = "C:\log\ex090310.log"
    Open LogFile For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            Debug.Print buf
            Sleep 1
        Loop
    Close #1
End Sub

Sleepは、指定した時間だけ処理を停止する命令です。引数はミリ秒単位ですから「Sleep 1000」で1秒停止します。上記のように指定した「Sleep 1」は、0.001秒になります。

0.001秒とはいえ、Sleepは処理を停止するのですから、マクロの実行速度はそれだけ遅くなります。上記のマクロなら、単純計算で「0.001秒×20万回=200秒」だけ余計に時間がかかります。しかし、マクロは速度を追求するだけではありません。このマクロがバックグラウンドで実行している間に、別の仕事をできるのですから、仕事全体を考えれば効率的と言えるでしょう。