- PR -

処理が止まるようになった

1
投稿者投稿内容
メロン
会議室デビュー日: 2005/03/16
投稿数: 2
投稿日時: 2009-03-10 15:59
いつもお世話になっております。

Windowsアプリケーションで、
クライアントからソケットで受信し、SQLSever2000との処理を行い、ソケットでクライアントに送信するという
ものを作りました。
.NETFrameworkの
System.Threading.Thread クラス
System.Threading.Moniterクラス
System.Collections.Queueクラス
を特に使用して作成しています。
画面上とファイルにログを書く処理があり、その排他にMoniterクラスを使用しています。

このアプリケーションが稼働していたサーバが老朽のため、
新しいサーバに移行しました。
(旧サーバは、Windows Server 2000、2CPU)
このアプリケーションは、.NETFramework1.0(VisualStudio2000でビルド)で構築しました。

新しいサーバでこのアプリケーション(プログラムの修正なし)、実行したら、非同期にスレッド内で処理が止まる現象が発生しました。
旧サーバでは、処理が止まるような現象は発生していませんでした。(5年間)
特にクライアントからのソケット受信後のMoniter.Enterを行ったときに1秒〜7秒、処理がとまるようです。

社内のサーバでもテストを行いましたが、現象が起きません。
このアプリケーションを.NETFramework1.1(VisualStudio2003でビルド)、
.NETFramework2.0(VisualStudio2005でビルド)と構築し直しましたが、現象が改善されません。

新サーバのスペックは以下の通りです。
CPU : クアッドコア インテル?Xeon?プロセッサーE5420(2×6MB L2キャッシュ 2.50GHz 1333MhzFSB)× 2
メモリー : 4GB(4×1GB 1R)667Mhz Fully Buffered DIMM ECC DRR2メモリ
OS : Windows Server 2003 R2 Standard Edition with SP2 日本語版
ギガビットイーサネットコントローラ(NIC) × 2
新サーバには、iSCSIイニシエータを使用し、ストレージを増設しています。

社内のスペックは以下の通りです。
CPU : クアッドコア インテル?Xeon?プロセッサーX5365 @3.00GHZ
メモリー : 4GB
OS : Windows Server 2003 R2 Standard Edition with SP2 日本語版


このような現象の理由と解決方法を、ご存知の方がいましたら教えて頂きたいです。
宜しくお願いします。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2009-03-10 18:42
こんにちは。

全然回答にはなっていないのですが…

引用:

メロンさんの書き込み (2009-03-10 15:59) より:
特にクライアントからのソケット受信後のMoniter.Enterを行ったときに1秒〜7秒、処理がとまるようです。



Moniter.Enterってスピンロックでブロックしているようですが、

ループに入れているPAUSE命令(rep nop)の待ち時間ってどのくらいの範囲あるのだろう??と思ってみたり

IA-32 インテル ® アーキテクチャ ソフトウェア・デベロッパーズ・マニュアルより抜粋
http://download.intel.com/jp/developer/jpdoc/IA32_Arh_Dev_Man_Vol2B_i.pdf
引用:

PAUSE - Spin Loop Hint

この命令はインテルPentium 4 プロセッサで導入されたが、すべてのIA-32 プロセッサ
に対して互換性がある。初期のIA-32 プロセッサにおいては、PAUSE 命令はNOP命令
と同じような動作をする。インテルPentium 4 プロセッサとインテル Xeon プロセッサ
は、事前定義された待ち時間としてPAUSE 命令を実装している。この待ち時間は有限
であり、プロセッサによってはゼロである場合もある。




確かめるには、こっち↓メソッドを使用したほうが良さそうであるけど、いろいろ試せるほど手元にPCが無い(汗)
Thread.SpinWait メソッド

甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2009-03-10 21:51
一番ありそうなのはコーディングミスで、例外発生時などにリリースしてないとか。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2009-03-10 21:51
一番ありそうなのはコーディングミスで、例外発生時などにリリースしてないとか。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2009-03-10 22:49
推理ですが、たぶん、こういう場合は、潜在化していたバグが、CPU数の違いで顕在化しただけだろうと思います。
一時的に、タスクマネージャーで、プロセスを選択して右クリックで「関係の選択」などを選び、CPUを1個だけにして動かしてみて、挙動が改善するかどうかを試されてはどうでしょうか。もしこれで改善したならば、ほかにもいろいろな方法でこういう指定ができますのでそのような回避方法でしのぐか、あるいは、CPU数がらみのバグを見つけて根本的に修正するか、のどちらかでしょうか。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2009-03-11 16:55
こんにちは。

引用:

unibonさんの書き込み (2009-03-10 22:49) より:
推理ですが、たぶん、こういう場合は、潜在化していたバグが、CPU数の違いで顕在化しただけだろうと思います。



私もそうでだろうとは予想しているのですが…

(マルチスレッドプログラミングでは常識ですが)ロックは必要最小限の期間でちゃんとリリースしているのでしょうかね?
リリースが遅いために、別スレッドでかなりの待ち時間が発生してしまっているとか!?



あと以下余談(独り言)ですが…
引用:

Tdnr_Symの書き込み (2009-03-10 18:42) より:
ループに入れているPAUSE命令(rep nop)の待ち時間ってどのくらいの範囲あるのだろう??と思ってみたり



計測してみると Celeron(2.66GZ)CPUでは、
PAUSE命令(rep nop命令)は1回あたり 約0.21μ秒程度でした。
NOPが(何もしないループと比較考慮すると)計測不能なくらい短いのに対して、かなり停止することが分かりました。
ただ何度か試しましたが、PAUSEの停止時間のブレはそんなにないように思いました。

C++コード
コード:
int _tmain(int argc, _TCHAR* argv[])
{
	DWORD dwStartTick = ::GetTickCount();
	DWORD dwTick;

	for (long l = 0; l < 1000 * 1000 * 1000; l++) {
		__asm { rep nop }
		/*
		__asm {
			nop
			nop
		}
		*/
	}

	dwTick = ::GetTickCount() - dwStartTick;
	printf("%d\\n", dwTick);

	return 0;
}



C#コード
コード:
static void Main(string[] args)
{
	int dwStartTick = System.Environment.TickCount;
	int dwTick;
/*
	for (long l = 0; l < 1000 * 1000 * 1000; l++) 
	{
	}
*/
	System.Threading.Thread.SpinWait(1000 * 1000 * 1000);

	dwTick = System.Environment.TickCount - dwStartTick;
	System.Console.WriteLine(dwTick.ToString());

}


メロン
会議室デビュー日: 2005/03/16
投稿数: 2
投稿日時: 2009-03-16 16:24
引用:

unibonさんの書き込み (2009-03-10 22:49) より:
推理ですが、たぶん、こういう場合は、潜在化していたバグが、CPU数の違いで顕在化しただけだろうと思います。
一時的に、タスクマネージャーで、プロセスを選択して右クリックで「関係の選択」などを選び、CPUを1個だけにして動かしてみて、挙動が改善するかどうかを試されてはどうでしょうか。もしこれで改善したならば、ほかにもいろいろな方法でこういう指定ができますのでそのような回避方法でしのぐか、あるいは、CPU数がらみのバグを見つけて根本的に修正するか、のどちらかでしょうか。



みなさん、回答ありがとうございました。

上記に書かれていることを試しましたが、解決できませんでした。
(タスクマネージャーで、プロセスを選択して右クリックで「関係の選択」などを選び、CPUを1個だけにして動かしてみる)


ちなみにCPU数がらみのバグとは、どういったコードを組んだときなのでしょうか?

ご回答、宜しくお願いたします。
ぱてお
常連さん
会議室デビュー日: 2008/03/07
投稿数: 41
投稿日時: 2009-03-17 13:43
マルチスレッドのプログラムの場合、スレッド間の同期に関しては
能動的にタイミングを取らないと動作環境が変わった関係で動きが変わってしまうことは
よくあります。同期オブジェクト等を使わずにスレッドの処理の終了順に依存している
ような部分があれば、状況のよってはスレッドの終了順が変わってしまって
うまく同期できないケースもあります。

元々、スレッドは行儀よく順番に動作するとは限りませんから
うまく同期が取れていないと特定のスレッドばかり処理が進んでしまうケースも
あったりします。スレッド絡みの不具合の場合はそういうケースも検討の範囲に
入れたほうが良いと思います。
スレッドのそういった仕様はMSDN上にも記載されていますが、
XPとVistaでこの辺の動作に違いが出てきているようで、
XPでは動いていたのにVistaではうまく行かないケースもあるみたいです。
仕様上は上記のように書かれていたけれど、XPでは実装の関係で偶々うまく
噛み合っていたと言うケースもあると思います。

スレッド絡みで思いつくことといったらこの位でしょうか。
1

スキルアップ/キャリアアップ(JOB@IT)