次: Memory Usage, 前: Pure Storage, 上: GNU Emacs Internals
プログラムがリストを作成したり、(ライブラリをロードするなどして) ユーザーが新たに関数を定義すると、 それらのデータは普通メモリへ置かれます。 普通メモリが足りなくなると、Emacsはオペレーティングシステムに 1kバイトの倍数のブロックでメモリ割り当てを要求します。 各ブロックは1つの種類のLispオブジェクトに使いますから、 シンボル、コンスセル、マーカなどはメモリの異なるブロックに分離されます。 (ベクトル、長い文字列、バッファ、特定の編集向けデータ型などの 比較的大きなものは各オブジェクトごとに独立のブロックを割り当てるが、 短い文字列は8kバイトのブロックに詰め込む。)
あるメモリ部分をしばらく使ってから、 (たとえば)バッファを削除したり オブジェクトに対する最後の参照を削除するなどして 当該メモリを解放することはよくあることです。 Emacsには、このような放置されたメモリを回収する ガベッジコレクタ(garbage collector)があります。 (この名前は伝統的だが、 『ガベッジリサイクル』のほうがこの機能を直観的に表すかもしれない。)
ガベッジコレクタは、Lispプログラムから現時点で参照可能な すべてのLispオブジェクトを探して印を付けることで動作します。 まず、すべてのシンボル、それらの値、それらに関連付けられた関数定義、 および、スタック上の任意のデータは参照可能であると仮定します。 参照可能なオブジェクトから間接的に辿れる任意のオブジェクトも 参照可能です。
印付けが終ったときには、無印であるすべてのオブジェクトは ゴミ(ガベッジ)です。 Lispプログラムやユーザーがなにをしようと、 無印のオブジェクトに辿り着く方法はないのでそれらを参照することは不可能です。 無印のオブジェクトを使っているものはいないので、 それらのメモリ領域は再利用できます。 ガベッジコレクタの2段目の動作(『掃く』(sweep))は、 無印のオブジェクトのメモリ領域を再利用できるようにすることです。
掃き作業では、未使用のコンスセルを自由リスト(free list)に入れて、
将来の割り当てに備えます。
シンボルやマーカについても同様です。
参照可能な文字列は8kバイトのブロックより小さな領域を占めるように詰め込み、
不要になった8kバイトのブロックは解放します。
ベクトル、バッファ、ウィンドウ、他の大きなオブジェクトは、
malloc
やfree
を使って個別に割り当てたり解放します。
Common Lispに関した注意: 他のLispと異なり、GNU Emacs Lispでは、 自由リストが空になってもガベッジコレクタを呼び出さない。 そのかわりに、オペレーティングシステムにメモリ割り当てを単純に要求し、gc-cons-threshold
バイトを使い尽くすまでは処理を継続する。つまり、ガベッジコレクタを明示的に呼び出した直後のLispプログラムの部分では、 (プログラムのその部分で2度目にガベッジコレクタを呼び出すほど 多くのメモリを使わないと仮定すれば) その部分を実行中にはガベッジコレクタが呼ばれないことを保証できるのである。
このコマンドはガベッジコレクタを実行し、 使用中のメモリ量に関する情報を返す。 (まえのガベッジコレクタの起動後に
gc-cons-threshold
バイト以上のLispデータを使うと 自発的なガベッジコレクタの起動を引き起こす。)
garbage-collect
が返すリストにはつぎの情報が含まれる。((used-conses . free-conses) (used-syms . free-syms) (used-miscs . free-miscs) used-string-chars used-vector-slots (used-floats . free-floats) (used-intervals . free-intervals))例を示す。
(garbage-collect) => ((106886 . 13184) (9769 . 0) (7731 . 4651) 347543 121628 (31 . 94) (1273 . 168))各要素の意味はつぎのとおりである。
- used-conses
- 使用中のコンスセルの個数。
- free-conses
- オペレーティングシステムから得たメモリであるが 現在未使用なコンスセルの個数。
- used-syms
- 使用中のシンボルの個数。
- free-syms
- オペレーティングシステムから得たメモリであるが 現在未使用なシンボルの個数。
- used-miscs
- その他の使用中のオブジェクトの個数。 マーカ、オーバレイ、ユーザーに見えないある種のオブジェクトを含む。
- free-miscs
- オペレーティングシステムから得たメモリであるが 現在未使用なその他のオブジェクトの個数。
- used-string-chars
- 使用中の文字列の総文字数。
- used-vector-slots
- 存在するベクトルの要素の総個数。
- used-floats
- 使用中の浮動小数点数の個数。
- free-floats
- オペレーティングシステムから得たメモリであるが 現在未使用な浮動小数点数の個数。
- used-intervals
- 使用中のインターバルの個数。 インターバルとはテキスト属性を表現するために使う内部データ構造である。
- free-intervals
- オペレーティングシステムから得たメモリであるが 現在未使用なインターバルの個数。
この変数が
nil
以外であると、 Emacsはガベッジコレクションの始まりと終りにメッセージを表示する。 デフォルト値はnil
であり、そのようなメッセージを表示しない。
この変数の値は、ガベッジコレクションのあとで つぎにガベッジコレクションを起こすまでに Lispオブジェクトに割り当てるべきメモリバイト数である。 コンスセルは8バイト、 文字列は1文字1バイトと数バイトのオーバヘッドといった具合である。 バッファの内容に割り当てたメモリ量は数えない。 この閾値を越えてもただちにつぎのガベッジコレクションは起こらず、 つぎにLispのエバリュエータが呼ばれときに起きる。
最初の閾値は400,000である。 より大きな値を指定すると、ガベッジコレクションの起動回数が少なくなる。 ガベッジコレクションに費す時間を減少できるが、 全体のメモリ使用量を増加させる。 大量のLispデータを作成するようなプログラムを実行するときに設定する。
10,000までの小さな値を指定すると、 ガベッジコレクションの回数を増やせる。 10,000未満の値が意味を持つのはつぎにガベッジコレクションが起きるまでである。
garbage-collect
は閾値を10,000に戻す。
garbage-collect
が返す値は、データ型ごとのLispデータのメモリ使用量です。
対照的に、関数memory-limit
は、
Emacsが現在使用中のメモリ総量に関する情報を与えます。