ありがたいことに404 Blog Not Found様がレスポンスを返してきてくれていて、うれしかったので調子にのってさらに補足追加。


手を上げろ!抵抗は無意味だ!
お調子者! ランキング!




しかし、これだとどんどん成長するファイルに関しては、realloc()しまくりでそれはそれで大変そうな気がしないでもないです。例えば、

dd if=/dev/zero of=/mnt/tmp/foo.tmp bs=1m count=256
cat /dev/null > /mnt/tmp/foo.tmp

とした場合、foo.tmpのsizeは0になりますが、foo.tmpのために割り当てられた256MBはそのままですよね、rm /mnt/tmp/foo.tmp するまでは。

 

これは、たぶんtmpfsをまだ誤解いしてるような気がする。

えと、まずmalloc/freeのfreeしても実はメモリを開放せずにライブラリが抱え込んで次のmallocに備えるんだよー、ってのはユーザー空間のセマンティクスなのでカーネル空間で動く奴らは基本的に開放したら即座にカーネルの空きメモリに戻ります。
カーネル内でもslabアロケーター(サイズが小さく、かつ、しょっちゅうallocされるものだけ使っている)やつらはキャッシュしやがりますが、ページサイズ(4k)超えるようなサイズのアロケートでそんなことはありえません。

また、reallocはまったく発生しません。なぜなら仮想ー物理メモリ変換を実施しているのはOS自身なのでOSはバラバラの物理メモリをユーザプロセスに見せる必要が出たとき(mmapされたとき)だけ連続アドレススペースにマッピングするだけだからです。

さらに言えば、tmpfsのメモリ管理機構ってのはざくっと言ってしまえば、普通のfile systemがバックエンドにブロックデバイスを持つ代わりにスワップを持つ。ただそれだけのfs。
だからメモリが少なくなってきて普通のfsがHDDにデータを書き出してメモリをあける所でかわりにスワップに書き出す。ただそれだけのこと。

それじゃあ、なんでtmpfsが普通のfsより速くなるかというと
・(fsによるが)普通のfsはディスクの不整合を防ぐためにunlinkなどのいくつかの操作を同期的にディスクに書き込む。tmpfsにはそれがない
・普通のfsはHDDを念頭においたHDDシーク最小化ソートルーチンを通るがtmpfsはそんな無駄なものは通らない
そのぐらい、実はあんまり違わない。
別にスワップが発生した段階でtmpfsがほかのfsに比べて特別優遇されるわけでもない。

つまりtmpfsの体感速度の向上ってのはスワップが発生したときではなく
(スワップ多発したら体感は最悪なので少々の事はわかるまい)
スワップが発生しないときに、(ディスク整合性の為の)不要なディスク書き込みが発生せず
かつ、RAMディスクと異なりメモリ(RAMディスク)をメモリ(ページキャッシュ)でキャッシュするような
無駄遣いをせず、かつ未使用メモリをOSに明け渡すのでその分スワップが発生する確率が減るところにあると言える。

分かる人にだけわかるように説明するとLinuxにおいては、tmpfsのmmapとanonymous mmapの違いは
tmpfs上ファイルはファイル名を持つゆえに複数ファイルで共有できる。ぐらいの違いでしかない。
(コードは共通化されてないけどやってることはほぼ同じだわさ)

予断になるが、ramfsもページキャッシュそのものだが、バックエンドを持たないので常にon memory.

だから、たとえば、404 blog not found様のエントリで問いかけられておられるよなコマンドを実行したとすると


$ cd /dev/shm
$ free
total used free shared buffers cached
Mem: 255928 247544 8384 0 35284 83980
-/+ buffers/cache: 128280 127648
Swap: 524280 0 524280

$ dd if=/dev/zero of=tmptmp bs=1M count=256
dd: writing `tmptmp': デバイスに空き領域がありません
読み込んだブロック数は 125+0
書き込んだブロック数は 124+0

$ free
total used free shared buffers cached
Mem: 255928 252432 3496 0 660 81516
-/+ buffers/cache: 170256 85672
Swap: 524280 90328 433952


124Mの書き込みに対して(メモリが少ないので256Mはできなかった。申し訳ない)

(バッファ分差し引き後の)使用メモリ+40M
swap usedが約90M増加

90+40=130 で計算あってるよね。



$ ls -l
合計 127964
-rw-rw-r-- 1 mkosaki mkosaki 130899968 2月 17 13:17 tmptmp



$ cat /dev/null > tmptmp
$ free
total used free shared buffers cached
Mem: 255928 171124 84804 0 1448 43836
-/+ buffers/cache: 125840 130088
Swap: 524280 3076 521204


そしてここに注目。

mem usedが80M減、cachedが40M減

/dev/nullを書き込まれた瞬間に、いままでのページキャッシュは参照カウントが0になるので
通常のキャッシュ破棄規則によって破棄されていく。

通常のfsでもディスクに書き出す前にもう一回書き出されたら、いままでのキャッシュを保持し続けることはないわけで、それとまったく同じ
(だってfs非依存部コードだもん)

なので、いきなりOSのfreeメモリが増える。
メモリが少ないマシンで実行したので、いまいち綺麗に124Mづつ増えたり減ったりしていないが
だいたいの傾向はつかめると思う。

なので、blog not found様がいうanonymous mmapでいいじゃん。は真だけども、
anonymous mmapのが速いはず。ってのは偽ね。おんなじ処理するから。
(ちょっとウソ、read/writeシステムコール自体のオーバーヘッドがあるので数バイトづつの読み書きを一々read/write呼びまくったらかなり遅くなる)
tmpfsの存在意義は昔ながらのコードをピクリとも修正せずに高速化できることにあるのだから、これは欠点とはいえまい。

というわけでまとめると
・mdはメモリをメモリでキャッシュするので、tmpfsより遅くなると思う
・tmpfsはanonymous mmapと比べてそう遜色ない速度が出る
・tmpfsはreallocもしないし、いらないメモリはちゃんと即座に開放する


P.S. OSのdisk cacheが賢ければ、tmpfsみたいな仕組みはあまりいらないという意見もありえます。昔はmfs(FreeBSDの古い方のRAM Diskの実装)とかよく使っていたのですが、今ではあまり使ってませんね。ただ、mdのような仕組みというのはdisk imageの実装には最適で、FreeBSDではmdの出現によりmfsとvn(disk image)が統一されてます。



実はわたしはつい最近までデジタル家電分野で組み込みLinux製品をつくり続け、今現在はスパコン分野でLinuxやっているというLinux屋さんの中ではかなり特殊な経歴の持ち主なのだが、上記意見には納得いかない部分があります。

たとえば、組み込みですとブロックデバイスはフラッシュメモリになるのですが、広く知られているようにフラッシュメモリは書き込み回数に上限があるため一時ファイルごときで一々書き込んでいたらとても家電に要求される10年無修理機器は実現できない

また、スパコンでいえば、デスクトップやサーバーと異なりずーーと高負荷状態が続くので空いてる時間がない。
だからキャッシュの空いてる時間にディスクに書けばいいやん哲学とは相性が悪い。

とかとか。

たぶん、デスクトップ分野でキャッシュが賢ければ理論は100%正しく、サーバー分野でもYahooみたいな
一部のずーーと高負荷状態サイト以外は大丈夫なのだとは思いますが、そういう例もあるということで

・・・脱線すぎですね。


ps
実は浅学なものでvnをLinuxのループバックデバイスと同じとしか理解していなかったので、
vnとmdが統合できるってのが目からウロコでした。
ぜんぜんコードに共通点なさそうに思えまする・・・・

FreeBSDも正攻法OSに見えて、実は結構強烈ですね。


追記: 実は今回の件があるまでfreeコマンドって使ったことなかったので、第一稿ではfreeコマンドの説明が間違っていた。
幻の原稿をよんだひと、すまぬ