- PR -

ASP.NETのmemoryLimitの上限が800MBまでの理由について

1
投稿者投稿内容
ryuuji
ベテラン
会議室デビュー日: 2003/07/10
投稿数: 53
お住まい・勤務地: 東京都
投稿日時: 2005-11-24 13:28
.NET Framework v1.1
Windows 2000 Server
物理RAM4GB

上記スペックのサーバ機にて運用中にASP.NET配下の全アプリケーションがOutOfMemoryExceptionを発生し続けサーバダウンするという現象がありました。解析結果からASP.NET Webアプリケーションの一つにバグがあり、ある条件で実行すると500MB近くのサーバメモリを消費してしまう事が分かりました。

その調査中、以下のURLを見つけました(残念ですが日本語はありません)。そこには物理RAMの最大容量に合わせてmemoryLimitを調節するよう書かれており、800MBを超えてしまうような設定は問題である、と書いてあります(書いてある気がします。。。)。例にもある通り物理RAM4GBに対してはmemoryLimitを60%から20%へ調節すべきとあります。

ここで質問なのですが何故(どういう計算で)上限が800MBになるのでしょうか?原文には仮想アドレス空間2GBがどうたらこうたら書いてあるのですが理解できませんでした(訳もおかしくなってます)。ご存知の方いましたらご教授願えませんでしょうか。

ちなみにboot.iniで/3GBと追加すると1800MBまで安全に使えるようになるともありました。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/monitor_perf.asp

下記は関連する部分を日本語訳したものです(誤訳等あれば教えて頂けると幸いです)。
----------------------------
Private Bytes. aspnet_wp.exeが保持している現在の確保済みメモリ(単位:バイト)のサイズ。メモリリークは一貫した、継続したPrivate Bytesの増加により見極められます。メモリリークを検出するためにはこれが最も良いパフォーマンスカウンタです。

IIS5.0の場合、Private bytesの上限値はconfigurationセクションの<processModel memoryLimit=/>に設定します。IIS6.0の場合〜関連しないので省略〜。aspnet_wp.exeのPrivate bytesはこの上限値と比較され、いつこのプロセスを再起動するか決定します。System.Web.Caching.CacheもPrivate bytesとこの上限値により、いつキャッシュからアイテム(つまりメモリ)を削除するかを決定され、これよりaspnet_wp.exeが再起動されてしまうのを回避します。ページングと特に大量のメモリ消費に起因するaspnet_wp.exeの再起動を回避するには物理RAMの60%が上限値として推奨されます。KB330469についても参照して下さい。大量のプロセスが稼働しているサーバ上でASP.NETがPrivate bytesの監視を失敗してしまう問題を解決しています。このhotfixは大量のプロセスが稼働していてもキャッシュメモリマネージャが正常に機能するようにも修正してくれます。

キャッシュメモリマネージャとaspnet_wp.exeの再起動が正常に機能するようこの上限値を調節することは重要です。例えばmemoryLimitがデフォルト値(60%)のままの4GBの物理RAMを搭載したサーバマシンがあるとします。この設定では問題になります。この物理RAMの60%は2.4GBです。これはデフォルトの仮想アドレス空間2GBより大きい事になります。それでは上限値にはいくつを設定すれば良いのでしょうか?

幾つか考慮しなければならない事があります。まず第一に仮想アドレス空間上限(通常2GB)の"Process\\Virtual Bytes"が600MB以内である場合、OutOfMemoryExceptionの発生が劇的に増加し始めます。次に試験では"Process\\Virtual Bytes"が"Process\\Private Bytes"を600MBまでしばしば超えていることを示しています。この差はGCにより管理されているMEM_RESERVE領域(メモリが必要なときにGCに素早くメモリ確保させます)に一部起因しています。これらをひっくるめると"Process\\Private Bytes"が800MBを超えると、OutOfMemoryExceptionの発生が増加する事を暗示しています。この例ではマシンは4GBの物理RAMを搭載しているので、OutOfMemoryExceptionが発生する状況を回避するには上限値を20%に設定する必要があります。あなたはこれらの数値の最大値を求める試験をしてみるかも知れませんが、もし安全に稼働させたいのであればこの例の値で十分です。

まとめると、memoryLimitの値は物理メモリの60%より小さい値か800MBに設定して下さい。.NET Framework v1.1は3GBの仮想アドレス空間をサポートしていますので、boot.iniに/3GBを追加することで上限として800MBの代わりに1800MBまで安全に使用することができます。

〜あまり関係無いので省略〜
----------------------------
ryuuji
ベテラン
会議室デビュー日: 2003/07/10
投稿数: 53
お住まい・勤務地: 東京都
投稿日時: 2006-07-05 14:23
今更ながらですが・・・

最近になって

1 GB 以上の RAM がある場合、/3GB スイッチが必要

を見つけ、こういう事なのかな、と思ったことを纏めてみました。考えが間違っていたら教えて頂けるとうれしいです。

1. プロセスは仮想アドレス空間(2GB)上限など気にせず、メモリが必要なった場合に必要なだけメモリを確保しようとする(OSに要求する?)
2. 既定の設定ではプロセスに割り当てられる仮想アドレス空間は2GB、これを超えてアクセスしようとするとOSがエラーを発生させる(OutOfMemoryException?)
3. 物理RAM4GBで、memoryLimit=60(%)だと2.4GBまでキャッシュマネージャ(?)がSystem.Web.Caching.Cacheからアイテムを削除しない
4. System.Web.Caching.Cacheが仮想アドレス空間の上限2.0GB当たりまでメモリを確保し続けると2.に当たりOutOfMemoryExceptionが発生する

よってタイトルに書いたように別に800MBが上限ではなく、仮想アドレス空間を越えないように物理RAMとmemoryLimitが調整されれば良いのかなと思いました。ということは物理RAM4GBでmemoryLimit=50(%)でぴったり上限2GBに収まるので、この設定でも問題なさそうな気がします(テストできる環境はもうありませんので実証できませんが)。


# ちなみに最近になって一部日本語訳されたようです(MSDN原文の章構成とマッピングされていないのは何故?)
第 6 章 「ASP.NET パフォーマンスの向上」
第 17 章 「.NET アプリケーション パフォーマンスのチューニング」
1

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