Path: sran265!katsu From: katsu@sran14.sra.co.jp (Katsuhiro Watanabe) Message-ID: Date: 12 Mar 92 19:19:26 Organization: Software Research Associates, Inc.,Japan In-reply-to: ono@soft.kme.mei.co.jp's message of 23 Jan 92 01:48:44 GMT Newsgroups: fj.unix Subject: Re: resource Distribution: fj References: <2735@icscA1.kme.mei.co.jp> <2810@icscA1.kme.mei.co.jp> おそらく jp で一番 follow が遅い渡邊@SRAです。 記事 <2810@icscA1.kme.mei.co.jp> で ono@soft.kme.mei.co.jp (N.ono@AI2) さんいはく > > > 命題: > > > 「最小限のスワップ領域と実メモリで > > >   実質的に問題のないスピード(スワップやページアウトが頻発しない)で > > >   開発したアプリケーションを動かしたい。」 > > > >  さては、UNIX を冷蔵庫か洗濯機か電気釜あたりの家電機器に安く > > 組み込むために、メモリーとディスクをけちろうという話でしょう? :-) > > ずばり、その通りです。 > 「だったら、おまえは洗濯機に何メガのメモリとディスクを積めば気が済むんだ?」  なるほど。洗濯機は振動でハードディスクを載せられないので、スワップ 機器にも、特別の配慮が必要ですね。  以前どこかのニュースグループで、洗い、すすぎ、脱水の各段階について 洗濯機を機能分散して各段階をパイプラインでつなげば、洗濯槽と水資源の 利用効率が高まって、高速かつ効率的に洗濯できるという発表があったような 気がします。もちろん負荷分散や危険分散への応用も考えられます。  洗濯機に Unix を載せれば、パイプやソケットなどのプロセス間通信を用いて 上のような機能分散の実装が容易になると思います。また、NFS が利用可能なら、 空いている洗濯槽をリモートマウントしてつかえる可能性もあるかもしれません。 広域ネットワークにつながれば、ちょっと面白いかも。  ただ、洗濯という仕事の性質上、Unix の開放的な哲学と合わない部分も ある気がします。ps(1) してみたら洗濯物の種類があらわになってしまったり、 洗濯ドメイン内で uid が統一されていなくて大騒ぎ(どんな?)になったり。  さて、主記憶とスワップ領域の見積りの件です。もともとの質問に具体的な 議論を期待する点が強調してあったので、基本的にはうまくいかないだろう という立場に立ちつつも、もう少し問題点を具体的に表現してみます。 (以下の話は 4.3bsd を仮定)  まずスワップは、プロセスが占める記憶域(text,data,stack,...)を、 同時に走る可能性のあるプロセス群についてスワップブロックを合計して、 あらゆる時刻でその合計を越えているようにすればよいので、比較的に 楽でしょう。各プロセスの実装に関する深い知識と統計があって、どの プロセスが同時に走るかの正確な見通しがあれば、スワップは悪くても 最大のスワップブロック単位(dmmax)程度の粒度(誤差は1個とか2個?)で 見積りができると思います。 (テキストとデータで、スワップ空間の割り当て方が違うことには注意。 テキストセグメントのスワップ空間の大きさは変化せず、ほとんどの場合 数ページクラスタぐらいの誤差で見積りができると考えられます。)  一方、主記憶の方は難問です。ページングの頻度が現実的に許容できる 程度という要求は、空きメモリーがほとんどの時刻で lotsfree 以上で あると解釈することにしましょう。また、プロセスの大きさは定常状態では 大きくは変化せず、そのワーキングセット(ここではこの言葉は、プロセスが 初期化後に定常的な状態になった時、以降の仕事を実行するために必要となる 全てのページの集合という意味に使います。この意味だと、ワーキングセット 全体が駐留していれば page in は起こらないことになります。)は、 そのプロセスの実装に関する十分な知識を持って統計をとることで、 他の要素と比較して少ない誤差で見積もれるものとしましょう。すると、 粒度 1MB程度での見積りは可能な場合もある(常にではない)という 私の予想を述べます。  少なくとも次の3つの点は主記憶の見積り時に問題になるでしょう。 (1)主記憶量が決まるのが先で、カーネルテーブルの大きさはそれに依存する (2)プロセス以外で、普通のカーネルデータ領域外に物理メモリを必要とする 要素、例えばディスクバッファやネットワークプロトコルについては、 振舞いがよくわからない (3)各プロセスのワーキングセットを見積もるのは難しいことが多い (1)主記憶の最初の firstfree まではカーネルとカーネル内データに使われます。 また、maxfree より上の部分はカーネルメッセージバッファーに使用されます。 maxfree - firstfree の部分が、ユーザーメモリとして利用されます。  それならば、対象システムと同じカーネルを使っているシステムで firstfree と maxfree を調べて、プロセス群のワーキングセットと lotsfree 分が一緒にここに収まるようにすれば解決するはずです。ところが、 カーネルの種々のテーブルの大きさは、主記憶の大きさに応じてブート時に 決定されます。つまり主記憶量が決まってからでないと、firstfree の値 すなわち、どれだけユーザープロセスに主記憶が割り当て可能かが決まらない のです。まあ、百ページも二百ページも違う訳ではないかもしれません。 (lotsfree の方は に定数で書いてあるところを見ると 多分固定なので、安心してよいと思います。) (2)カーネルデータとメッセージバッファーを除いた部分全てがユーザー プロセスに割り当て可能な訳ではありません。 ・ネットワークプロトコルに使用される記憶域は mbuf データ構造を軸に 管理されていますが、この mbuf 用の物理メモリーはブート時には 4KB 割り当てられていて、256KB を上限に増加していきます。 ・ディスクバッファーのことも考えなければなりません。その大きさは、 やはり主記憶の大きさに依存してブート時に決められます。ただし、 主記憶の最初の 2MB までに対して 10%、残りに対して 5% ということに なっているので、一応逆算が可能です。(実装によって違うかも)  元々の 4.3bsd ではバッファーページは静的に予約されると思いますが、 動的にとるようにする試みがいくつかの OS でなされているようです。 当然、問題は一層複雑になります。(例えば NEWS OS 4.1C/R では、 バッファーに使われる物理ページ数 buffer_pages が動的に変化します。 を参照されたし。これは SONY での変更なのか tahoe か 何かに由来する変更なのか私はわかりません。) ・さらに NFS も関係してくるかもしれませんが、私には全くわかりません。  ………要するにポイントは、ユーザープロセス群で占めることができる 記憶域が一定でなく、よしんばプロセス群のワーキングセットが完全に 求まっていても、主記憶の量と関係づけることは難しいということです。 (3)そしてもちろんプロセスのワーキングセットを見積ることにも問題が 残っています。 (a)ここまではワーキングセットを、定常時に必要となる全てのページの 集合として考えてきたが、全てのページの駐留を要求することの妥当性 (例えばほとんど参照されないページは page out されていい場合もある。 ここに、以前にも指摘があったように「主記憶最小」と「paging 最少」の 間のトレードオフがある。) (b)見積もり方法自体の難しさ  しかし、これらはうまく解決できる「場合もある」でしょう。  うまくいく場合とは、プロセス空間内で、頻繁に参照されるページと、全く 参照されないページがはっきり分かれているような場合です。例えば、 次のような単純な小さい構造を持っているプロセスがこの場合にあたります。 main() { 初期化(); while (1) {何かやる();} /* 何かやる() は十分小さい */ }  この場合、(a)に対応しては、駐留して欲しいページと欲しくないページの 区別は明確です。(b)に対応しては、別のシステムで動かして仮想記憶を 逼迫した状況に追い込んでみると、ワーキングセット分だけが駐留して残って、 その量が測定できることが期待できます。  一方で、分岐していたりループが長大なために、参照の頻度が高くならない ようなページを含むプロセスではうまくいかないでしょう。(自由ページは Least Recent Used リストで管理されることを考えに入れる。) while (1) { switch (状態) case こういう状態: こうする(); break; case 珍しい状態: 珍しさに驚く(); break; default: ああする(); } のようなやつや、 while (1) { これやる(); あれやる(); あれもやる(); ……… }、 といった感じのものがこれにあたります。(a)駐留して欲しいページの 基準として、どの程度の参照頻度に線を引くのか(珍しさに驚く() は 駐留すべきか、駐留していなくてもいいかの判断)という点と、 (b)実機と異なる条件下で paging activity 等を測定して、どれだけ 実機上での現実を反映させられるかの技術、の2点は問題となるでしょう。  なお、対象プロセス以前に、daemon 類が走っていると思いますが、 daemon 類のワーキングセットの見積りにもまったく同じ苦労が必要で あることを忘れてはなりません。  実際にやってみたわけではないので説得力が非常に小さいですが、 上のことをまとめると、実は予想できる場合もある気がします。例えば、 (1) firstfree は気分で見積もっても 100KB も違わないでしょう。 (2a) ネットワークは、洗濯機のような組み込み機器なら全然使わないか (LAN につながなくとも、例えば localhost があって mbuf を使うことが あり得ることに注意)とてもよく使うのどちらかだから、最大か最小を仮定。 これでも高々 200KB 程度しか間違っていない。 (2b) ディスクバッファーは、主記憶の最初の 2MB までに対して 10%、残りに 対して 5% というのを信じる。(ページ割当が動的な場合はお手あげ?) (3)ワーキングセットの見積りは、(小さい少数のプロセスが動くとして、 うーん、………これでも誤差がどうなるか不明ですね)「適当」にする  ようにすれば、粒度 1MB ぐらいでの見積りができることもある……… というつもりで書き始めたのですが、やはりあまり説得力ないですね。 「主記憶 8M の標準モデルでいい?」「lisp 動かすから16M に増設して。」 などと粒度 8MB の会話をするよりはいいかなと考えたのですが。(まあ、 洗濯機で洗濯中に lisp を動かすことはないでしょうけど。)  結論として、小手先の技で見積りをやったところで、それが合ってるか 合ってないか信頼できないのですから、結局最後は実機上で統計を とりながら試さざるを得ないと私は主張します。  もしかしてカーネルのソースを見ると、もっと沢山のことがわかって、 問題のいくつかが解決できるのかもしれませんね。ソースを読んで しまったがために投稿しないでいる hacker も、多分いると思います。  参考までに、dmmax, firstfree, ... 等のカーネル変数を見るには、 # adb -k /vmunix /dev/mem _dmmax/X などとします。 ----____----____ 渡邊克宏 SRAソフトウェア工学研究所