私が32GBのメモリを搭載したwindows PCで検証したところ、1週間ほどで32GBのメモリを使いつくしてフリーズすることが確認できた。100%再現性がある。メモリ不足になると、タスクマネージャーが起動できないし、シャットダウンメニューを出すことすらできなくなり、強制電源断以外には回復方法がなくなる。
何がメモリを消費しているか調べるとページキャッシュであった。ページキャッシュはファイルシステム(HDDやSSD)に対するキャッシュのことだ。ファイルシステムからデータを読み出すときはそのデータをメモリ上にもコピーする。次に同じデータを読み出すときはファイルシステムからではなくメモリから読み出せば速い。ファイルシステムへデータを書き込むときは、そのデータをメモリ上に書き込んで書き込んだつもりになる。後で機会があるときにメモリ上のデータをファイルシステムに実際に書き込む。書き込んだつもりで済ませるので書き込みが速い。このデータを置いておくメモリをページキャッシュと呼ぶ。ページキャッシュのおかげでファイルシステムの読み書きが高速になる。
ページキャッシュのうち、読み出しに使われるキャッシュはいつ解放(消去)してもかまわない。大元のデータはファイルシステムに存在するから、キャッシュがなくなっても読み出しが遅くなるだけだ。それに対して書き込みに使われるキャッシュは、キャッシュ上のデータをファイルシステムに書き込んだ後でないと解放できない。書き込む前にキャッシュを解放してしまうと、本来書き込むはずだったデータが消えてしまいファイルシステムに書き込まれないことになるので、OSやアプリが誤動作してしまう。
この書き込み前のページキャッシュがメモリを消費してwindows OSはフリーズする。windows OSは、ページキャッシュを解放すべきときにしないという重大な設計ミスがある。まっとうなOSの設計ポリシーでは、OSやアプリに必要なメモリが足りなくなったとき、ページキャッシュを解放する。ファイルシステムを高速化するページキャッシュにメモリを使用するより、OSやアプリにメモリを使用する方が優先度が高いので当然のことだ。
書き込み前のページキャッシュを解放するときには、ページキャッシュの内容をファイルシステムに書き込まなくてはならない。この作業をsyncとかflushと呼ぶ。この作業はOSが管理していて、定期的に、また必要なときにsyncを行っている。必要なときというのは、例えばメモリが足りなくなったときだ。
linuxの実験では、ユーザープログラムがメモリを必要としたとき、自動的にOSがページキャッシュを解放している。普通にOSを設計したらこうなる。ところが、windowsはこれをしない。メモリが不足したらページキャッシュをsyncして解放すればいいだけなのにしない。ページキャッシュが永遠にメモリを使用していて、使用量が増えることはあっても減ることはない。これではいくらメモリを積んでいてもやがてメモリ不足になり、windowsはフリーズしてしまう。
フリーズを防ぐためにはユーザーはwindows PCを2,3日おきにシャットダウンかサインアウトをしなくてはならない。シャットダウンかサインアウトを行うと、ページキャッシュはsyncされてメモリは解放される。それ以外にページキャッシュを解放する方法がない。
この仕様というかバグのコードがどこに書かれているか私は知らない。これだけ有名なバグなのに未だに直せていないということはmicrosoftの中の人も分からないのではないかと疑っている。アプリの行儀が悪いときだけこの現象が起こり、行儀の悪いアプリを自動的にkillできないのでOS側をいくら修正しても直らないのか。行儀の悪いアプリが管理しているメモリなら仕方がないが、ページキャッシュはOSが管理しているのだからアプリに関係なく解放できるはずなのだが。
windows 7以前での情報だがmicrosoft サポートページでこの問題の解説がある。メモリ管理に需要ベースのアルゴリズムを用いているのが良くないと読める。その後OSのバージョンアップやパッチにて改善しようとしたらしいが、うまく行っていない。需要ベースで考え無しにページキャッシュにメモリを割り当てるのを止めない限り、問題は解決しないだろう。
0 件のコメント:
コメントを投稿