タイトル | : Re^4: 容量が増えると動作速度が遅くなる |
記事No | : 13921 |
投稿日 | : 2009/07/31(Fri) 22:05 |
投稿者 | : 魔界の仮面弁士 |
> みなさんのご意見お願いいたします。
ループ内で行われている write_data = write_data & data1 & "," & data3 & "," & data2 & vbCrLf の部分を write_data = write_data & (data1 & "," & data3 & "," & data2 & vbCrLf) にするだけで、処理効率がアップしますよ。(理由は後述します)
しかし、もっと効率の良い方法があります。 それは既に No.13914 で YuO さんが回答している方法なのですが、 出力ファイルと入力ファイルを同時に開いて、順次書きこんでいくという物です。
つまり、現在の
fData = FreeFile() Open 入力ファイル For Input Access Read As #fData Do Until EOF(fData) Input #fData, data1, data2, data3 write_data = write_data & data1 & "," & data3 & "," & data2 & vbCrLf Loop Close #fData fData = FreeFile() Open fName For Output Access Write As #fData Print #fData, write_data Close #fData
のような処理を、
fIn = FreeFile() Open 入力ファイル For Input Access Read As #fIn fOut = FreeFile() Open 出力ファイル For Output Access Write As #fOut Do Until EOF(fIn) Input #fIn, data1, data2, data3 Print #fOut, data1 & "," & data3 & "," & data2 Loop Close #fIn, #fOut
という形式にするという物です。これにより、相当の高速化が期待できます。
> 下の通りデータを並べ替えているので一気にバイナリで読んで書き込むこともできないので > あきらめました。
文字列連結を行うと、そのたびに 新たな文字列領域の確保 → 確保された領域へのコピー → 以前の領域を破棄 という作業が繰り返し行われる事になります。
短い文字列同士の連結であれば、確保サイズが小さいため、さほど時間はかからないのですが、 長い文字列に対して連結する場合には、この確保と解放にかかる時間が問題となります。
そこで、「長い文字列」に対して文字列を連結させる回数を減らす工夫が必要です。
ひとつ実験。下記を試してみてください。
Private Sub Command1_Click() Dim T As Single, L As Long, S As String T = Timer For L = 1 To 10000 S = S & CStr(L) & "TEST" Next Debug.Print Format(Timer - T, "#,0.000秒") End Sub
Private Sub Command2_Click() Dim T As Single, L As Long, S As String T = Timer For L = 1 To 10000 S = S & (CStr(L) & "TEST") Next Debug.Print Format(Timer - T, "#,0.000秒") End Sub
いずれも同じ処理を行っています。違うのは、文字列連結部分を S = S & CStr(L) & "TEST" 'Command1 S = S & (CStr(L) & "TEST") 'Command2 にしているだけです。
両者は当然、同じ文字列を生成しますが、後者の方が高速に処理されます。 実際、これを当方環境で試してみると、平均時間で ループ 10000 回 20000 回 30000 回 Command1 …… 約0.6秒 …… 約3.8秒 …… 約10.8秒 Command2 …… 約0.3秒 …… 約1.8秒 …… 約5.3秒 という速度差になりました。処理時間がほぼ半分になっていますね。
これは Command1 の方の処理が '『S = S & CStr(L) & "TEST"』 X = S & CStr(L) ' S が大きいので、処理に時間がかかる S = X & "TEST" ' X が大きいので、処理に時間がかかる
に相当する処理が行われているのに対し、Command2 の方では '『S = S & (CStr(L) & "TEST")』 X = CStr(L) & "TEST" ' 短い文字列なので、処理時間が短い S = S & X ' S が大きいので、処理に時間がかかる
という処理になるためです。そのため、処理時間を約半分で済ませることができます。
そしてこれが先の 'write_data = write_data & data1 & "," & data3 & "," & data2 & vbCrLf write_data = write_data & (data1 & "," & data3 & "," & data2 & vbCrLf) という修正案を提示した理由となります。
|