🐘 片付けを忘れたサーバー
STAGE 2 ― メモリという棚 ―
クリア 0 / 3
STAGE 2

メモリという棚

借りる・返す・中身が残る
🎯 ミッション
メモリを番地つきの箱の棚として説明し、「借りる」「返す」の意味と、返した箱にも中身が残ること、1件のリクエストが借りられる量に上限があることを説明できれば合格。
未達成
ねこ博士
前回の「机の上のメモ」の正体を考えよう。コンピューターにはメモリという部品がある。プログラムが動いている間、計算の途中の数や文字を置いておく作業場所だ。
うさ美
パソコンの説明に「メモリ16GB」と書いてあるものですか?
ねこ博士
そう、それだ。メモリは、小さな箱が一列にずらっと並んだ巨大な棚だと思えばいい。箱1つには0から255までの数が1つ入る。この箱1つ分の大きさを1バイトという。16GBなら、箱がおよそ160億個並んでいることになる。
うさ美
160億個も! そんなにたくさんあったら、どの箱に何を入れたか分からなくなりそうです。
ねこ博士
だから、どの箱にも端から順に番号がついている。この番号を番地(アドレス)という。プログラムは「1000番の箱に5を入れる」「1000番の箱の中身を読む」というように、番地で箱を指定して使うんだ。
番地つきの箱の棚。プログラムは「何個分の箱がほしい」と管理係に頼み、空いている箱をまとめて借りる。使い終わったら返す。返した箱は、中身が消されないまま「空き」の印だけがつく
うさ美
箱は、プログラムが好きなところを勝手に使っていいんですか?
ねこ博士
勝手に使うと、ほかの処理が使っている箱を上書きしてしまう。だから、棚には管理係がいる。プログラムは「箱を8個ください」と管理係に頼み、空いている箱をまとめて借りる。これをメモリの確保という。使い終わったら「返します」と言って返す。これがメモリの解放だ。
うさ美
図書館で本を借りて返すのに似ていますね。
ねこ博士
そうだね。ただ、図書館と違う点が1つある。返した箱の中身は、消されないんだ。管理係は帳簿に「この箱は空き」と印をつけるだけで、中に入っていた数はそのまま残る。
うさ美
どうして消さないんですか? 消したほうが安全な気がします。
ねこ博士
速さのためだよ。プログラムは1秒に何百万回も箱を借りたり返したりする。そのたびに中身を0で塗りつぶしていたら、それだけで時間がかかる。次に借りた人は、どうせ自分の値で上書きしてから使う。だから消さない。ふつうはそれで困らないんだ。
うさ美
「ふつうは」ということは、困る場合があるんですね。
ねこ博士
ある。たとえば、借りた箱にまだ何も書いていないのに、書いたつもりで中身を読んでしまう場合だ。その話は、処理が途中で止まるときのことを考えるときにしよう。先に、PHPでの箱の借り方を見ておきたい。
うさ美
お願いします。
ねこ博士
PHPは、リクエストを1件受けるたびに、そのリクエスト専用の箱の区画を用意する。プログラムの中で文字や配列を作るたびに、その区画から箱を借りる。そしてリクエストが終わると、区画の箱をまとめて返す。1つずつ返し忘れがあっても、最後にまとめて返すから漏れない、という作りだ。
うさ美
前回の「1件ごとに全部片付ける」の約束は、この「まとめて返す」のことなんですね。
ねこ博士
その通り。それからもう1つ。1件のリクエストが借りられる箱の数には上限がある。PHPでは memory_limit という設定で決める。たとえば128MBなら、1件で約1億3千万個の箱までだ。
うさ美
上限がないと、どうなるんですか?
ねこ博士
1件のリクエストが、ばかでかいデータを送りつけられたりして箱をどんどん借りると、ほかのリクエストの分まで使い切ってしまう。サーバー全体が止まりかねない。だから上限を決めておいて、超えそうになったらそのリクエストを打ち切る。この状態をメモリ不足、英語の Out Of Memory を略して OOM という。
; php.ini の設定の例(1件のリクエストが借りられる上限) memory_limit = 128M ; 上限を超えると、PHPはこういうエラーを出してそのリクエストを打ち切る Fatal error: Allowed memory size of 134217728 bytes exhausted
うさ美
打ち切る、というのは、プログラムの途中でいきなり止めるということですか?
ねこ博士
そう。そして、この「途中でいきなり止める」というのが、片付けを難しくする原因の1つなんだ。次は、処理が途中で止まるとき、プログラムの中で何が起きるのかを見よう。
【このステージの成果】 メモリ=番地つきの箱の棚。箱1つが1バイト(0〜255の数が1つ) 管理係に頼んで箱を借りる=確保、返す=解放 返した箱の中身は消されない(速さのため。「空き」の印がつくだけ) PHPはリクエストごとの区画から箱を借り、終わるとまとめて返す 1件が借りられる量には上限(memory_limit)。超えるとメモリ不足(OOM)で打ち切り

確認クイズ

Q1. メモリの箱1つずつについている番号を何という?

Q2. プログラムが借りていた箱を返した(解放した)とき、箱の中身はどうなる?

Q3. 1件のリクエストが借りようとした箱が memory_limit を超えると、どうなる?

← トップへ