QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

ワーカプロセスのメモリ使用量について

ASP.NET + Oracle8i
SERVER:Windows2000 Server SP4
CPU:1.6GB
使用可能メモリ:3.7GB

メモリの使用量については過去ログにていろいろ拝見してframeworkにより
ガーベージコレクションが自動で行われることなどは分かりました。
ただ現在、ワーカプロセス(aspnet_wp.exe)のメモリ使用量が300MG程度の時には
全く正常に終わるアプリケーションがメモリ使用量が500MG程度になると
(その時の全体メモリ使用量1.7GB程度)
「この操作を完了するのに十分な記憶域がありません」
というエラーを返してきてしまいます。

使用可能メモリはまだ余裕があるのですがなぜなのでしょうか?

machine.configのprocessModelは以下のとおりです。

memoryLimit="60" で3.7GBの60%が2.22GBなので特に問題はなさそうなのですが。

質問者:よねちん

回答

D, an alchemistさん長々お付き合いくださってありがとうございます。

1) memoryLimit
消えるとマズいのであれば memoryLimit は高めにしてリクエスト流入量自体を絞りこんで使用メモリを抑えるか、既にご検討されているように、

memoryLimitはサーバの物理メモリの何パーを使うかを設定すると思っていたのですが。
例えば500MBのメモリならmemoryLimit=20にすれば500MB*20%=100MBをワーカプロセスの
メモリが使用できると思っていたのですがどうなんでしょうか?

メモリを使用しないようにコードを書き直すか(不正にメモリを確保している犯人がいるならそいつを捕まえるか)、になるんじゃないかと思います。

その不正にメモリを確保している犯人探しがつらいです。

とりあえずIISのログを採取して各画面がGet,Postしている時間やバイト数を見ているの
ですがいまいち決め手になるようなものがありません。

D, an alchemist.さんの言うとおりにDetasetのゴミがたくさん残って開放できないのかな
と思います。

あと近頃ワーカプロセスが何のエラーも返さずに予期せぬエラーで落ちてしまいます。
メモリを多く使用しているのでもなく突然落ちるのです。
1.0のframeworkでそんなバグがあったと思うのですが1.1でありパッチも最新なので
関係ないし・・・
でも何らかのエラーが発生してワーカプロセスが落ちると使用している人が全員使えなく
なってしまうのも困ってしまいます。

投稿者:よねちん

編集 履歴 (0)

レス遅くなりました。

1) memoryLimit
memoryLimit の設定に関してはアプリの運用的な設計になるかと思います。この設定値を超えて落とされれば、InProc であればもちろん Session 変数等々は消えてなくなりますから、エラーを取るか or データ消去を取るか、ではないかと。

オンメモリなデータが消えても構わないのであれば、requestLimit を適当に設定して数リクエストさばいたらどんどんリサイクルさせてしまうという手もあると思います。

消えるとマズいのであれば memoryLimit は高めにしてリクエスト流入量自体を絞りこんで使用メモリを抑えるか、既にご検討されているように、メモリを使用しないようにコードを書き直すか(不正にメモリを確保している犯人がいるならそいつを捕まえるか)、になるんじゃないかと思います。

2) GC
パフォーマンスカウンタ .NET CLR Memory の %Time In GC を見ていると、定期的にスパイクすると思います。このタイミングで GC が動いているんだと思います。あまりに大きい領域を確保/開放しまくったり、コードで GC.Collect() しまくってジェネレーションを意図的に古くしない限り、GC が作動しなくなるという事はないんじゃないかなぁと思います。

3) メモリの使用状況
市販のプロファイラ等を使うのがいいのかなぁと思いますが、私はよくわかりません。

なお、パフォーマンスカウンタ .NET CLR Memory の #Total comitted Bytes や #Total reserved Bytes が右肩上がりに上がっていき、それが Workingset と比例しているならマネージドな何かが確保され続けているんだと思います(Web アプリなら、大抵は Session 変数に入れた DataSet なのではないでしょうか)。

それに対して、これらのカウンタはあまり増えていかないのに、パフォーマンスカウンタ Process の Private Bytes が Workingset に比例してどんどん増えているような場合はアンマネージドな何かが確保され続けているんだと思います(COM コンポーネントで使ってる何かがリークしている、とか、ですかね)。

hope it helps
D, an alchemist.

投稿者:D, an alchemist

編集 履歴 (0)

すると重い処理を複数端末で処理をしても300MB程度でGCが効いてくれるように
なりました。とりあえずこれで様子見をします。

GCは作動してくれるようにはなりましたが、減っては増え減っては増えで
増える方が多くて現在405MBまで膨れてきました。
memoryLimit=14にて現在500MBでワーカプロセスが自動で終了するので落
ちるのも時間の問題かもしれません。
メモリ解放を個々のプログラムできちんと行ってないような気がします。
多分Sessionにデータなんかを入れ込んでいるものがあると推測してます。

そこでお聞きしたいのは、こんな時には個々のプログラムを全て調べて
いくしかないのでしょうか?本数的には100本くらいのプログラムがあり
かなりの調査工数がかかってしまいます。

できれば現在のメモリを使っている諸悪の根源をみつけてそこを集中的に
調査していきたいのですが、それをするにはどんな手法があるでしょうか?

noderaさん 返信ありがとうございます。

COMを正しく解放できているかチェックしたほうが良いかもしれません。GCは、COMやアンマネ>ージド?のメモリー管理まではやってくれないので、そのあたりでメモリーリークしている可能>性もあります。

COMの解放ができているかを確認する方法はあるのでしょうか?

投稿者:よねちん

編集 履歴 (0)

こんにちは。

ラベル発行ツールとASP.NETがどのような形でやり取りされているか、イマイチ分かりませんが、COMオブジェクトを直接ASP.NETのプログラム上から利用されているのであれば、COMを正しく解放できているかチェックしたほうが良いかもしれません。GCは、COMやアンマネージドのメモリー管理まではやってくれないので、そのあたりでメモリーリークしている可能性もあります。

投稿者:nodera

編集 履歴 (0)

ガーベージコレクションの効くクライアント端末と
メモリが増え続けるサーバとの違いで気になること
があったので、以下の事をクライアント端末でテス
トしました。

500(512)の物理メモリのあるクライアント端末で

重い処理を続けて流した場合にmachine.configの
memoryLimitを以下のようにして流してみました。

memoryLimit=5の場合

初回の処理が30MB程度かかる為に
aspnet_wp.exeが落ちる。エラー内容は
メモリ使用が 25 MB (使用可能 RAM の 5 パーセント) を超えたため、
aspnet_wp.exe (PID: 736) が繰り返されました。

memoryLimit=20の場合(推定では100MB程度は使用できるはず?)

この場合ですと65MBのところでGCが効いているような感じで
それ以上のメモリは使用しない。(少しづつ減っている)

memoryLimit=40の場合(推定では200MB程度は使用できるはず?)

この場合ですと85MBのところでGCが効いているような感じで
それ以上のメモリは使用しない。(少しづつ減っている)

memoryLimit=60の場合(推定では300MB程度は使用できるはず?)

この場合ですと100MBのところでGCが効いているような感じで
それ以上のメモリは使用しない。(少しづつ減っている)

以上のようになります。

推定なのですが、サーバは物理メモリを5000MB搭載していて
memoryLimit=80にしてあります。この場合は4000MBまで使用
可能の設定(2GBまでしか意味ないのでしょうがw)

この場合はGCがまだ余裕ある為に効かないのかなと思います。
そしてメモリはどんどん増えつづけ、500MBくらいになると

D, an alchemistさんの返信にもあるとおり

私の個人的な経験では、ASP.NET のワーカープロセスがまともに動くのは Workingset が 800MB くらいまでで、それをこえると OutOfMemoryException

いろんな場面でエラーになるのかな?と思うのですがどんな
もんでしょうか?

なのでサーバのmemoryLimitを10にして500MBくらいまでにしたら
良いのかなと勝手に推測してるのですが、誤っているでしょうか?

ただ運用サーバの為に誤ったことはできないので、詳しい方に
ご教授して頂きたいと思います。

宜しくお願いします。

投稿者:よねちん

編集 履歴 (0)

D, an alchemistさん返信ありがとうございます。

今見てたのですが、どうもワーカプロセスが500MB付近になると
.NETでもOut of memoryを出しているようです。
おかしい現象はテストマシンにて重い処理を故意的に流してみると
メモリエラーになる前にガーベージコレクションが効いてメモリ使用量
は途中でかなり開放されますが、本番のマシンではメモリ使用量がどん
どん上昇していく一方で減らないような気がします。

後、朝方にServerのイベントビューアにエラーが発生しています。
これも気になるのですが・・・

日付:2005/05/30 ソース:RAID_SERVER
時刻:9:32 分類:デバイス
種類:エラー イベントID:140
ユーザ:N/A
コンピュータ:XXXXXXXXX←サーバのコンピュータ名

説明:
Raid Server Alert
Message:Registration Sever Connection Lost

投稿者:よねちん

編集 履歴 (0)

こんにちわ。

Win32 のプロセスのメモリ空間限界は 2 GB(例外アリ)だったと思います。なので、システム全体の物理メモリ量などはあまり関連しないような気がします。
また、processModel の設定は ASP.NET が強制的に終了させる限界値なので、超えたとしてもエラーが出るわけではないと思います。なのでこれもあまり関連しないような気がします。

「この操作を完了するのに十分な記憶域がありません。 (0x8007000e)」
は COM の E_OUTOFMEMORY に対応したエラーメッセージだと思います。.NET な領域でメモリが足りないのであれば System.OutOfMemoryException が発生すると思います。

なので、
Oracle の接続にもし OLEDB Provider をご利用であれば、その状況に何か現象を出すためのトリガーがあるような気がします。その他、COM 的なものを疑ってみるといいのではないかと思います。

なお、
Oracle 8i の oci.dll か何かはマルチスレッドに対応していないみたいです。となると Web アプリにはあんまり向かないじゃないかと思います。

http://support.oracle.co.jp/open/owa/external_krown2.f_detail?c_criterion=%7B16381%7D&i_key=CyberOOW&c_document_id=16381

hope it helps
D, an alchemist.

投稿者:D, an alchemist

編集 履歴 (0)

noderaさん返信ありがとうございます。

そのエラーがでる処理なのですが
ラベルを発行しているプログラムで出ます。
某社のラベル発行ツールを使用しています。
処理的にはイメージを読み込み、その中に
情報を出力すると。ラベルが印刷できるよう
になってます。

他にもEXCELを作成し画面に浮き上がらせる
ツールなども使用しています。

両方の修正モジュールを見てみましたがそん
な現象は報告されてませんでした。

投稿者:よねちん

編集 履歴 (0)

D, an alchemistさん返信ありがとうございます。

こんにちわ。

Win32 のプロセスのメモリ空間限界は 2 GB(例外アリ)だったと思います。なので、システム全体の物理メモリ量などはあまり関連しないような気がします。

ここでお聞きしたいのが、その場合にはメモリ使用量はまだまだ増加しても
大丈夫なのでしょうか?ガーベージコレクションが早く実行されてメモリが
早く開放されて欲しいのですが、まだ開放する時ではないということなので
しょうか?怖いのがSessionをやたら使っているみたいでremoveとかがして
いないプログラムがかなりありそうなのですが、それらがメモリ上に残って
消せないという可能性もあるのですが・・・

また、processModel の設定は ASP.NET が強制的に終了させる限界値なので、超えたとしてもエラーが出るわけではないと思います。なのでこれもあまり関連しないような気がします。

この前、他のメモリが少ないマシンでテストした時には
ワーカプロセスがそのメモリを超すと自動的に終了しました。
その時にはサーバのイベントビューアにエラーとして出てました。
その時には一般の画面にはセッションタイムアウト(ワーカを落とす
とログイン情報が消えてしまうので)を返しているようです。

「この操作を完了するのに十分な記憶域がありません。 (0x8007000e)」
は COM の E_OUTOFMEMORY に対応したエラーメッセージだと思います。.NET な領域でメモリが足りないのであれば System.OutOfMemoryException が発生すると思います。

最初は
「この操作を完了するのに十分な記憶域がありません。 (0x8007000e)」
が出てましたがしばらくしてメモリ使用量がが700MBを超すと

今度は.netでSystem.OutOfMemoryException: メモリが不足しています。 が出てきました。

COM の E_OUTOFMEMORYが発生しその後にはASP.NETのOutOfMemoryExceptionが出て
いるようにもみえます。

COM の E_OUTOFMEMORYがでないようにするにはどのような手段があるのでしょうか?

タスクマネージャでエラー時にはこんな感じになってました。
---------------------------------------------------
タスクマネージャのパフォーマンスのタグ

**CPU使用率
1%〜20%程度

**合計
ハンドル 15491
スレッド 992
プロセス 75

**コミットチャージ
合計 1866412
制限値 5728080
最大値 2082256

**物理メモリ
合計  3799528
利用可能 1741648
システムキャッシュ 1854624

**カーネルメモリ
合計   131740
ページ  101912
非ページ 30668
---------------------------------------------
プロセスのタグ
aspnet_wp.exe 623,076 KB

---------------------------------------------

comのエラーが発生しているのとワーカプロセスの
メモリ使用量は切り離して考えた方が良いのでしょうか?

noderaさん返信ありがとうございます。

そうなるとASP.NETというより、そのラベル発行ツールが怪しいですね。
そのツールは、単独のアプリケーションなのでしょうか?それともライブラリ?(マネージドかそうではないのかでも変わってきますが、なんとなくアンマネージドかな)
メモリ使用量が300MBと500MBのときの違いはなんでしょう?
ツールが耐えられないようなイメージデータを渡しているとかないですか?

出力する帳票は300MBの時も500MBの時も同じものを出力するようにしていますので
ツールが耐えれないイメージデータを渡していることはないです。

私はワーカプロセスのメモリ使用量に着眼してしまっていましたが
帳票の出力ツールがCOMにデータを送る時にメモリが不足しているの
かもしれません。

もう少し調査をします。

投稿者:よねちん

編集 履歴 (0)

こんにちは。

CPU:1.6GB
CPU:1.6GHz
300MG / 500MG
300MB / 500MB

という突っ込みは置いといて、

>「この操作を完了するのに十分な記憶域がありません」
このエラーメッセージはどこから返されるメッセージなのでしょうか?
なんとなく.NETの例外っぽく無いメッセージですが。

この処理の中で、MS Officeとか何か別のアプリケーションやファイルを操作してるってことはないでしょうか?もしそのような処理が行われているのであれば、情報としてあわせて記述してもらえると、何かつかみ易いかと思います。

投稿者:nodera

編集 履歴 (0)

本番サーバのmachine.configのmemoryLimitの値を以下の設定を変えました。
物理メモリが3.7GBでしたので500MBを目安に14を設定しました。

すると重い処理を複数端末で処理をしても300MB程度でGCが効いてくれるように
なりました。とりあえずこれで様子見をします。

ただ本当に500MB以上のメモリを必要になる場合はワーカプロセスが自動で
落ちる危険性もありますが。そうなった時にはプログラミングの見直し、運用
の見直しが必要となることは覚悟します。

また結果は随時報告します。

投稿者:よねちん

編集 履歴 (0)

たぶん、
まずは E_OUTOFMEMORY を出しているのがどこのどいつで、何故エラーを出しているかのを突き止め、それから .NET な世界のメモリ状況について検討するのがいいと思います。

なお、
私の個人的な経験では、ASP.NET のワーカープロセスがまともに動くのは Workingset が 800MB くらいまでで、それをこえると OutOfMemoryException が頻発したり、CPU 100% になったりしたと記憶しています。

hope it helps
D, an alchemist.

投稿者:D, an alchemist

編集 履歴 (0)

こんにちは。

そうなるとASP.NETというより、そのラベル発行ツールが怪しいですね。
そのツールは、単独のアプリケーションなのでしょうか?それともライブラリ?(マネージドかそうではないのかでも変わってきますが、なんとなくアンマネージドかな)

メモリ使用量が300MBと500MBのときの違いはなんでしょう?
ツールが耐えられないようなイメージデータを渡しているとかないですか?

投稿者:nodera

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。