ログ出力を高速にするには?


K  2004-12-07 16:40:11  No: 87204  IP: [192.*.*.*]

VB6.0で作ったアプリケーションにログファイルを出力する関数を付けました。
しかし、その中身は
Open LogFile For Append Lock Write As #FileNo
Print
Close #FileNo
としているせいか、この処理をするのと、しないのとではかかる時間が
全然違います。
・入れない場合   0.454秒
・入れた場合    10.154秒
もっと高速にログを出力する方法がございましたら、ご教授願います。

編集 削除
java.lang.Nullpo  2004-12-07 16:52:03  No: 87205  IP: [192.*.*.*]

そんなに変わりましたか・・・。
ってことは、吐く量が結構膨大?

私は、ログを吐くとこをCで作って、
静的ライブラリ として使ったりしてます。
#define EXPORT extern "C" __declspec(dllexport) ですね。

どうしてもVBでやるとなると・・・

  ・Appendをやめて、別のファイルを毎回使うようにする。
  ・もし、書き込みが数回あるなら、1回にまとめるとか。
    (書く内容は、Stringの配列などにまとめとくと良い)

編集 削除
K  2004-12-07 16:54:33  No: 87206  IP: [192.*.*.*]

説明不足だったかもしれないので、補足します。
この関数は、各モジュール内の始め・終わり・エラー時・データを見たい所
など多々呼ばれるようになっています。
呼ばれる度に、ファイルをオープンして、書き込んで、クローズして・・・
というような感じです。

編集 削除
java.lang.Nullpo  2004-12-07 17:05:38  No: 87207  IP: [192.*.*.*]

> この関数は、各モジュール内の始め・終わり・エラー時・データを見たい所
> など多々呼ばれるようになっています。
> 呼ばれる度に、ファイルをオープンして、書き込んで、クローズして・・・
> というような感じです。

うーん、エラー時はそのまま終了するからいいとする。
始めも、まあ1回ぽっきりだし許容する。(ログの意味がなくなるし)
「データを見たい所」ってのは、"エラー時"または"終わり(正常終了時)"に
一気にやれば、いいのでは?

# やり方は、先に示したとおり。

編集 削除
K  2004-12-07 17:24:42  No: 87208  IP: [192.*.*.*]

エラーの発生場所が特定しやすいと思って入れたんですけど。。。

編集 削除
GOD  2004-12-07 17:31:21  No: 87209  IP: [192.*.*.*]

処理時間が短いようですし、毎回開くのではなく開きっぱなしはまずいですか?
もちろん終了時にはクローズしてくださいね。
オープン時にAppendを指定しているのでSeekする分よけいに遅くなっているので
はと予測。

編集 削除
de  2004-12-07 17:34:48  No: 87210  IP: [192.*.*.*]

全くの推測ですが、ハードディスクへのアクセスがボトルネックになり
どんな風にしても、そんなに速度は上がらないんじゃないでしょうか。
メモリに余裕があるならRAMディスクを導入してはいかがですか?

下記テストコードでハードディスク上では26秒
RAMディスク上では2.7秒でした

Private Sub Command1_Click()

  Dim i     As Long
  Dim dblT  As Double
  
  strLog = App.Path & "\Log.txt"
  dblT = Timer
  For i = 1 To 10000
    LogOut "テストメッセージ出力 " & Format(i) & "回目"
  Next
  Debug.Print Timer - dblT
  

  strLog = "G:\Log.txt"
  dblT = Timer
  For i = 1 To 10000
    LogOut "テストメッセージ出力 " & Format(i) & "回目"
  Next
  Debug.Print Timer - dblT

End Sub

Private Sub LogOut(strMsg As String) 

  Dim intF  As Integer
  
  intF = FreeFile
  Open strLog For Append As #intF
  Print #intF, Format(Now, "yyyy/mm/dd hh:mm:ss") & " - " & strMsg
  Close #intF

End Function

ちなみにRAMディスクは(http://www.ramdisk.tk)のものを使いました。

編集 削除
java.lang.Nullpo  2004-12-07 17:36:22  No: 87211  IP: [192.*.*.*]

> エラーの発生場所が特定しやすいと思って入れたんですけど。。。
ちゃんと正しい意図で説明を読んでますかね?

データできあがったところまでは、変数に溜めとけといったはずです。
エラーを吐くまえに「その溜めた分」を書けば、どこでエラーが起きたかはわかるんですが?

1件終える度に書き込む場合と、出来上がるものは変わらないハズ。

# また、GODさんの言うように開けっぱなしの方がいいでしょう。
# 1番最初に書くべきことだったのに、忘れてた・・・orz

編集 削除
hige7  2004-12-19 13:45:15  No: 87212  IP: [192.*.*.*]

API使えば早くなるよ。
CreateFile
WriteFile

編集 削除
ガッ  2004-12-19 15:07:07  No: 87213  IP: [192.*.*.*]

API使えば早くなるのか…

編集 削除
通行人  2004-12-19 20:58:38  No: 87214  IP: [192.*.*.*]

Win32 API:WritePrivateProfileStringを使ってみては?

編集 削除
ねろ  2004-12-19 21:25:03  No: 87215  IP: [192.*.*.*]

ファイルをオープンすると言う事は、ハードディスクにとっては
ファットエリアにヘッドを持って行って、そこで指定されたファイルの
情報を読み込み、その情報により、ヘッドを読み書きエリアまで持って
いかなくてはいけないのよね。
そしてクローズは読み書きエリアにあるヘッドを、ファットエリアに持って行き
更新情報を書き込んで終了となるわけで、オープンクローズのたびににハードディスク
のヘッドはファットエリアと読み書きエリアを行ったり来たりと忙しい。
要するに同じファイルのオープンクローズを繰り返すコードは効率が悪いと言う事です。
その為にメモリーというものが有ります。

>API使えば早くなるのか…
間違いなく速くなります。長いファイルだとVBの数十倍の速さで。
でも本質問とは関係ないですね。

編集 削除