プロが教えるわが家の防犯対策術!

元々他の人が作成したコードなのですが
    元はXPで使用 その時はそういった現象が出ていないようにも思えますが
    頻度の問題で気が付かなかったのかもしれません
    (現在も動いていますが特に問題が出ているということを聞いていません)

現在 Win7上のVC6(SP6)にて ini ファイルへの書き込み処理を行っている関数Aがあり
それを関数Bからコールしています
関数の関係は下に書いたようなイメージになります
その他複数スレッドなども存在し各種動作を行っています

問題なのは不定期に(頻度も少ない様ですが)関数Aの処理時間が
30秒以上かかることがあるようなのです(ファイルCのチェックにて確認)
もちろん通常は0~1秒程度しかかかっていません

なぜそのような現象が発生するのか要因がつかめずに悩んでいます
   (しかも30秒っていくらなんでもかかりすぎだろう   と)
考えられる可能性がありましたら何でもいいので教えていただけないでしょうか
   少しでも情報が欲しいので可能性・想像だけでも構いません
   (あまりにも現実離れした想像は困りますが)

関数B

    ファイルCに処理開始時間保存 (普通のファイル書き込み処理 追加モード)
    関数A
    ファイルCに処理終了時間保存 (普通のファイル書き込み処理 追加モード)


関数A

   特定 INI ファイルへの書き込み  使っているのは APIや標準関数のみ
   sprintf ・ WritePrivateProfileString   関数
   セクション・キー名など変えて 50回前後実行します(1つの ini ファイルです)


ウイルスバスターが動いている環境で 上記に類似したコードを動かしたときに
異常に処理負荷がかかったということは経験しています
(多分ファイルオープンクローズを繰り返しているためかなと想像しています)
   ただしこの時は時々とかいう問題では無いためすぐにわかりました

(上記現象は分かっているため)該当PC上ではウイルススキャンの類のソフトは
インストールしていません
閉塞LAN構築下に存在しているPCとなります
TCP/IP 通信 共有も行っているのでファイヤーフォールは無効にしています
あまり関係ないと思いますが DI/Oボード増設を行っています

その他については特殊な設定は行っていないと思っていただいて構わないと思います
(既に十分特殊という話もあるかもしれません)

一つのファイルへのオープンクローズを一気に50回前後繰り返すという
作りもいまいちなのですが 既に駆動しているプログラム・
ini ファイルの操作の手軽さということでそのような作りになってしまっています

簡単に他の形に置き換えられるのであればそれでもかまわないのですが
INIファイルの特定セクションや特定キーの一部データの更新という処置の為
自前でやるのにも現在躊躇している状態です
  -> こうすれば簡単に置き換えが可能だって話があればそういった情報でも構いません
          全ファイル読み込んだうえでセクションやキーをチェック該当部分を
          置き換え(バッファ操作)して最後に一括で書き込めばいい
          といったことは分かっています
          (それを自前でやってないのがini ファイルの操作の手軽で~~ということです)
             悩んでる間に作っちまえ という話もあるもかもしれませんが
             (微妙な諸事情もあるので)あえてそこには触れないでください

他に必要な情報があれば必要に応じて追記させていただきます

A 回答 (5件)

ローカルファイルにあるINIファイルを変更しているんですよね。


#ネットワーク越しに共有しているファイルとかじゃないかということ

それから、50回のオープンクローズを1回にしてみると、状況が変わるかとか、
関数Aをコールしない場合は、そういう事象は発生しないということも確認済?

構造を改善するのが一番よさそうだけど、例えば、その頻繁にアクセスするINIファイルは、
RAM上に置き(RAMディスク作成ツールでRAMドライブを作る)、RAM上での書き換えが終わったら、
ディスクに書くようにするとか。

この回答への補足

回答ありがとうございます

>ローカルファイルにあるINIファイルを変更しているんですよね。
そうです

>50回のオープンクローズを1回にしてみると、状況が変わるかとか、
此方に関しては質問文に書いたように躊躇している状態です

>関数Aをコールしない場合は、そういう事象は発生しないということも確認済?
頻度の問題確実に確認できているというわけではありません
今現状ではっきりしているのはその処理内で異様に時間がかかることがある
ということだけです

>構造を改善するのが一番よさそうだけど、例えば、その頻繁にアクセスするINIファイルは、
>RAM上に置き(RAMディスク作成ツールでRAMドライブを作る)、RAM上での書き換えが終わったら、

完全な構造変更というのが諸事象で難しい点もあるのですが
他で同様なことをやって逃げていた前歴がありました
   すっかり忘れ去ってました
   同様対処で発生事象が改善されたことも確認しています

システム上今からRAM DISKなどを構築するのは不安があるので
一旦作業用フォルダにコピー
そちらのファイルに対して現状の処理を行い終了後再度コピーする
といった方法がありますね

#1さんの書かれたように本当に都度オープンクロースしてるのかという話と
遅延書き込みとか影響ないのか 等ちょっとわからない点もありますが
やってみる価値はありそうな気がします

補足日時:2010/12/14 11:47
    • good
    • 0
この回答へのお礼

数点の可能性含め考えるとべき内容もある程度見当ついてきました

様子見のじょゆ教で時間がどれだけかかるか分からないので
一旦閉じさせていただきます

お礼日時:2010/12/15 20:44

あのー、「調査のためにコードを修正すること」まで躊躇ってませんか?


例えば、ファイルが他のプロセスによって専有されているかどうか、
その他のソースコードを読んで、ない「はず」というよりも、
自分のプロセスで当該ファイルをCreateFileの排他ロックで開く・閉じるを繰り返すようなコードを
書いて(関数B内でファイルのロックを握ろうとして)失敗することがあれば、
他のプロセスが握っているんだろうと思います。
#GetLastErrorで調べられると思います。

他にも、処理時間が30秒もかかっているときには、WritePrivateProfileStringの
戻り値は失敗を返してないか?とか、色々と調べるべきことがあると思います。

私なら再現頻度を調べて、1ヶ月に1回とかなら、時間的な制約でソースコードから
調査しますし、1日1回とかであれば、ログを各所に埋め込んだり、上記のような
調査用のコードを走らせてみます。

最終的にソースコードを書きなおすかどうかはともかくとして、
原因がソフト的な問題か、ハード的な問題か?を切り分ける必要はあると思います。
原因をしっかり突き止めないと、後々どこかでしわ寄せが来ます。

この回答への補足

>あのー、「調査のためにコードを修正すること」まで躊躇ってませんか?
そのつもりはないんですがそう見えたらすいません

>私なら再現頻度を調べて、1ヶ月に1回とかなら、時間的な制約でソースコードから
>調査しますし、1日1回とかであれば、ログを各所に埋め込んだり、上記のような
>調査用のコードを走らせてみます。
頻度とか含めて以前からログを各所に埋め込んだりしてという状態で
今のところまで来ているといった状態です

補足日時:2010/12/14 16:19
    • good
    • 0
この回答へのお礼

数点の可能性含め考えるとべき内容もある程度見当ついてきました

様子見のじょゆ教で時間がどれだけかかるか分からないので
一旦閉じさせていただきます

お礼日時:2010/12/15 20:45

No.1 です。



外付けのHDDが、中途半端に大きなバッファを持っていて、それがあふれたときに時間がかかる……というのも、可能性としては考えられますが、それだと、30秒は長すぎますね。

> XP以前の ini ファイル推奨時代は 書き込み終了させるための
> フラッシュ関数があったような記憶もあるのですが……

http://msdn.microsoft.com/ja-jp/library/cc429952 …
によると、Windows 95 では、
WritePrivateProfileString(0, 0, 0, filename);
でバッファをフラッシュするそうです。

この回答への補足

>WritePrivateProfileString(0, 0, 0, filename);
>でバッファをフラッシュするそうです
引数でしたか  そりゃ関数探しても見つからんわ
何かほかの言語と勘違いしてたのかもしれません

補足日時:2010/12/14 16:16
    • good
    • 0
この回答へのお礼

数点の可能性含め考えるとべき内容もある程度見当ついてきました

様子見のじょゆ教で時間がどれだけかかるか分からないので
一旦閉じさせていただきます

お礼日時:2010/12/15 20:45

質問内容からわからないことをいくつかお聞きします。


・開発環境はWindows7上との事ですが、
 実行環境も同等の環境でしょうか?

 >現在 Win7上のVC6(SP6)にて 
 とありますが、まず第1にVc6は
 既にサポートが終了されており、
 Vista以降のOSでは仮に動作したとしても、
 その保証がないことをご留意ください。


・既に質問者さんも経験がおありのようですが、
 別の関係ないプロセスがファイルをつかんでいる可能性は
 ありませんでしょうか?

 ウィルス対策ソフト以外に、バックアップ系の
 ソフトウェアなどが考えられます。


・ここからが主眼となりますが、
 マルチスレッドでも動作するということですが、
 排他処理などは行っていないのでしょうか?

 提示された処理内容からは当該の動作を
 行っていない様ですが、複数スレッドからの
 書き込みは少なくとも排他する必要があると思いますが
 もし排他している場合は、これで待たされているか、
 もしくはもっと下回りのドライバIOレベルでの読み書き
 排他に引っ掛かっている可能性があります。


・上記と似ていますが、複数プロセスで
 同じIniファイルを参照する可能性はないのでしょうか?

 この場合は、スレッド間の排他と、プロセス間の
 排他処理を両方行うことになり、待ち時間も
 ファイルIOの状況によっては、結構な物になると思います。

また、関数A,関数Bの呼び出され方ですが、
これらはアプリケーション実行中に定期的にINIファイルを
更新する処理があるという認識であっていますか?

INIファイルなどは、簡易的な使用方法として、
アプリケーション開始時に読み込み、
終了時に書き込みを行って保存しておくという
使い方が一般的だと思うので、
内部でキャッシュなどが行われる場合は
頻繁に更新された場合に、期待した動作に
ならない可能性があり得るのではないかと思います。

>こうすれば簡単に置き換えが可能
一番早いのは、WindosAPIはASCII用とWide用の為に、
WritePrivateProfileStringなどの関数はDefineで置き換えられているので
引数を同じにした関数を作成し、データ部分以外の引数を捨てて
fprintfなどで独自のフォーマットを使用して、読み書きを行う方法です。
関数の呼び換えを行うのは楽ですが、データのフォーマットを
考えなければなら無いためあまりお勧めできませんが。。。
#書き込みのみを一括にするという方法もあります。

適当ですが
--- header
#if defined( WritePrivateProfileString )
#undef WritePrivateProfileString
#endif
#define WritePrivateProfileString MyWritePrivateProfileString

VOID CloseMyPrivateProfileString( VOID );
BOOL OpenMyPrivateProfileString( LPCTSTR );
BOOL MyWritePrivateProfileString( LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR );

--- src
static FILE *fp = NULL;
BOOL OpenMyPrivateProfileString( LPCTSTR lpFileName )
{
 fp = fopen( FileName, "r+" );
 if ( !fp ) return FALSE;
 return TRUE;
}

VOID CloseMyPrivateProfileString( VOID )
{
 fclose( fp );
 fp = NULL;
}

BOOL MyWritePrivateProfileString(
 LPCTSTR lpAppName, // セクション名
 LPCTSTR lpKeyName, // キー名
 LPCTSTR lpString, // 追加するべき文字列
 LPCTSTR lpFileName // .ini ファイル
){
 int ret;
 ret = fprintf( fp, "[%s]\n", lpAppName ); //セクション
 if ( ret < 0 ) return FALSE;
 ret = fprintf( fp, "%s=%s\n", lpKeyName, lpString );
 if ( ret < 0 ) return FALSE;
 return TRUE;
}

この回答への補足

回答ありがとうございます

>開発環境はWindows7上との事ですが、
>実行環境も同等の環境でしょうか?
同じ環境です

>別の関係ないプロセスがファイルをつかんでいる可能性は
無い筈なんです(ソース上で探してるがそれらしいところは見当たらない)
(何処かでつかまっている可能性が高いのかなという気は確かにしています)
バックアップ系のソフトなども動かしていません
  特定用途限定PCとして使っているので動作に必要ではない
  他のアプリケーション類は動いていない(インストールもしていない)
  と考えていただいて構いません

>Vista以降のOSでは仮に動作したとしても、
>その保証がないことをご留意ください。
承知しています
いかんせん費用の問題とその部分でたまにそうなっているということで頭抱えています
↑があるので作成環境の問題じゃないんじゃない?  ってなことに

>排他処理などは行っていないのでしょうか?
これが困ったことに入り乱れてしまっているんです
  (致命的になりそうなところは行っています)

>同じIniファイルを参照する可能性はないのでしょうか?
該当ファイルに関して言えば他から参照の可能性はありません
ただ私としても何処かで該当ファイルがロックされてしまっている
ような可能性を一番に疑っています
   その要因となるようなところが見当たらない為
   なんでかがわからないといった状況です

別のファイルでも他のPCなどからLANアクセスされたりすると
影響あるもんなんでしょうかね?
(ここら辺がよくわからない所です  単純に考えれば影響はなさそうなんですが)

>これらはアプリケーション実行中に定期的にINIファイルを
>更新する処理があるという認識であっていますか?
定期的といえば定期的なのですがタイマーのような定期的なものではなく
データ更新されたとき一緒に更新されるといったものです

現状その時の書き込み処理をパスしても致命的にはなりそうもない事もあり
(全てパスすることはできないんですが条件的にパスできるときに発生しているように見受けられた為)
とりあえずそういった変更をして様子を見てもらっています

>INIファイルなどは、簡易的な使用方法として、
>  省略
>使い方が一般的だと思うので、
確かに・・・・・
私もあまり一般的な使い方だと思っていません
作ったときに手軽だからという一点だけでそのようになってしまっていて
今更状態といったところです
64K制限とかあったような気もしてるんですが動いてる
作成時(テストでは)問題なかったとかいうのもあったようで
64K は Win95時代でそうだったような気がするだけで
XPではその制限なくなってるんでしょうか?
  ※ 該当ファイル自体は64kもありません

>一番早いのは、WindosAPIはASCII用とWide用の為に、
#2さんへの補足に書いたのですが
一旦該当ファイルを作業用ファイルとして別名でコピー
コピー先に対して書き込み実行  ファイルを書き戻す
といった方法が一番手っ取り早くできそうかな   と思い当りました
書いていただいたコードも参考にさせていただきたいと思います

可能性含めまだしばらく情報を求めたい為
質問自体はまだしばらく閉じないつもりです

補足日時:2010/12/14 12:24
    • good
    • 0
この回答へのお礼

数点の可能性含め考えるとべき内容もある程度見当ついてきました

様子見のじょゆ教で時間がどれだけかかるか分からないので
一旦閉じさせていただきます

お礼日時:2010/12/15 20:44

もしかしたらですが、Windows 7 で動いているパソコンが、SSDを使っているということはないですか。


SSDは短時間にファイル処理をすると時々固まりますが。(最近は大丈夫なのかな?)

あと、ini ファイルをAPI経由で書き換えるのは、普通ですし、WritePrivateProfileString() が呼び出しの度に、実際にファイルをオープンクローズしているかは、微妙ですが。

この回答への補足

書き込みありがとうございます
この前I/F変わってから初めて質問したため 補足のつけ方がわからずに焦りました

>Windows 7 で動いているパソコンが、SSDを使っている
SSIDの使用はしていません
ただし? HDDの増設(SATA 500G)は行っており
そちらの増設DISKでプログラムを実行しています
増設HDD(or 標準HDD)でもそういった事象の可能性というのはありえるのでしょうか?
(可能性の話だけだったらあるとしか言えない質問かもしれませんね)

もう少し細かいPC環境的は
Win7(正確には英語OS)+ VC6(SP6 これも英語版)
 マザー P7P55D-E CPU i5 メモリ 4G  (自前組上)
 HDD 300G(C) + 500G(D) + 光学ドライブ(E)

>実際にファイルをオープンクローズしているかは、微妙
確かにそうですね
私もそこまで細かく確認しているわけではないですし
OS内部動作が絡んできてしまうので具体的な調べ方も思いつきません

XP以前の ini ファイル推奨時代は 書き込み終了させるための
フラッシュ関数があったような記憶もあるのですがそれらしき
関数がなんだったか忘れてしまいました(& 探し方が悪いのか見当たらない)
 ->そういった関数があるということは常に行っているのかも微妙
   ってことなのかもしれません

補足日時:2010/12/14 11:37
    • good
    • 0
この回答へのお礼

数点の可能性含め考えるとべき内容もある程度見当ついてきました

様子見のじょゆ教で時間がどれだけかかるか分からないので
一旦t辞させていただきます

お礼日時:2010/12/15 20:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!