Next: スタックに割り当てられたオブジェクト, Previous: 純粋ストレージ, Up: GNU Emacsの内部 [Contents][Index]
プログラムがリストを作成するときや、(ライブライのロード等により)ユーザーが新しい関数を定義する際には、そのデータは通常ストレージに配置されます。通常ストレージが少なくなるとEmacsはもっとメモリーを割り当てるようにオペレーティングシステムに要求します。シンボル、コンスセル、小さいベクター、マーカー等のような別のタイプのLispオブジェクトはメモリー内の個別のブロックに隔離されます(大きいベクター、長い文字列、バッファー、および他の特定の編集タイプは非常に巨大であり1つのオブジェクトにたいして個別のブロックが割り当てられて、小さな文字列は8kバイトのブロック、小さいベクターは4kバイトのブロックにパックされる)。
基本的なベクター以上のマーカー、オーバーレイ、バッファーのような多くのオブジェクトが、あたかもベクターであるかのように管理されています。対応するCデータ構造体にはunion
vectorlike_header
フィールドが含まれ、そのメンバーsize
にはenum
pvec_type
で列挙されたサブタイプ、その構造体が含むLisp_Object
フィールドの数に関する情報、および残りのデータのサイズが含まれます。この情報は、オブジェクトのメモリーフットプリントの計算に必要であり、ベクターブロックの繰り返し処理の際のベクター割り当てコードにより使用されます。
しばらくの間いくつかのストレージを使用して、(たとえば)バッファーのkillやあるオブジェクトを指す最後のポインターの削除によりそれを解放するのは非常に一般的です。この放棄されたストレージを再利用するためにEmacsはガーベージコレクター(garbage collector)を提供します。ガーベージコレクターは本質的には、いまだにLispプログラムからアクセス可能なすべてのLispオブジェクトを検索、マークすることにより動作します。これを開始するにはすべてのシンボル、それらの値と関連付けられている関数定義、現在スタック上にあるすべてのデータをアクセス可能であると仮定します。別のアクセス可能オブジェクトを介して間接的に到達できるすべてのオブジェクトもアクセス可能とみなされますが計算は“保守的”に行われるので、アクセス可能なオブジェクトの個数はいくらか過大に評価されるかもしれません。 accessible, but this calculation is done , so it may slightly overestimate how many objects that are accessible.
マーキングが終了してもマークされないオブジェクトはすべてガーベージ(garbage: ごみ)です。Lispプログラムかユーザーの行為かに関わらず、それらに到達する手段はもはや存在しないので参照することは不可能です。誰もそれを失うことはないので、それらのスペースは再利用されることになります。ガーベージコレクターの2つ目ののフェーズ(sweep: スイープ、一掃)ではそれらの再利用を計らいます(がマーキングは“保守的”に行われるのですべてのスイープが一度ですべての未使用オブジェクトをガーベージコレクトする保証はない)。
スイープフェーズは将来の割り当て用に、シンボルやマーカーと同様に未使用のコンスセルをフリーリスト(free list)上に配置します。これはアクセス可能な文字列は少数の8kブロックを占有するように圧縮して、その後に他の8kブロックを解放します。ベクターブロックから到達不可能はベクターは可能なかぎり最大のフリーエリアを作成するために統合して、フリーエリアが完全な4kブロックに跨がるようならブロックは解放されます。それ以外ならフリーエリアはフリーリスト配列に記録されます。これは各エントリーが同サイズのエリアのフリーリストに対応します。巨大なベクター、バッファー、その他の巨大なオブジェクトは個別に割り当てと解放が行われます。
Common Lispに関する注意: 他のLispと異なりGNU Emacs Lispはフリーリストが空のときにガーベージコレクターを呼び出さない。かわりに単にオペレーティングシステムに更なるストレージの割り当てを要求して、
gc-cons-threshold
バイトを使い切るまで処理を継続する。これは特定のLispプログラムの範囲の実行直前に明示的にガーベージコレクターを呼び出せば、その範囲の実行中はガーベージコレクターが実行されないだろうと確信できることを意味する(そのプログラム範囲が2回目のガーベージコレクションを強制するほど多くのスペースを使用しないという前提)。
このコマンドはガーベージコレクションを実行して使用中のスペース量の情報をリターンする(前回のガーベージコレクション以降にgc-cons-threshold
バイトより多いLispデータを使用した場合には自然にガーベージコレクションが発生することもあり得る)。
garbage-collect
は使用中のスペース量の情報をリストでリターンする。これの各エントリーは‘(name
size
used)’という形式をもつ。このエントリーでnameはそのエントリーが対応するオブジェクトの種類を記述するシンボル、sizeはそれが使用するバイト数、usedはヒープ内で生きていることが解ったオブジェクトの数、オプションのfreeは生きていないがEmacsが将来の割り当て用に保持しているオブジェクトの数。全体的な結果は以下のようになる:
((conses
cons-size used-conses free-conses) (symbols
symbol-size used-symbols free-symbols) (strings
string-size used-strings free-strings) (string-bytes
byte-size used-bytes) (vectors
vector-size used-vectors) (vector-slots
slot-size used-slots free-slots) (floats
float-size used-floats free-floats) (intervals
interval-size used-intervals free-intervals) (buffers
buffer-size used-buffers) (heap
unit-size total-size free-size))
以下は例:
(garbage-collect) ⇒ ((conses 16 49126 8058) (symbols 48 14607 0) (strings 32 2942 2607) (string-bytes 1 78607) (vectors 16 7247) (vector-slots 8 341609 29474) (floats 8 71 102) (intervals 56 27 26) (buffers 944 8) (heap 1024 11715 2678))
以下は各要素を説明するためのテーブル。最後のheap
エントリーはオプションであり、背景にあるmalloc
実装がmallinfo
関数を提供する場合のみ与えられることに注意。
コンスセルの内部的サイズ(sizeof (struct Lisp_Cons)
)。
使用中のコンスセルの数。
オペレーティングシステムから取得したスペースにあるがカレントで未使用のコンスセルの数。
シンボルの内部的サイズ(sizeof (struct Lisp_Symbol)
)。
使用中のシンボルの数。
オペレーティングシステムから取得したスペースにあるがカレントで未使用のシンボルの数。
文字列ヘッダーの内部的サイズ(sizeof (struct Lisp_String)
)。
使用中の文字列ヘッダーの数。
オペレーティングシステムから取得したスペースにあるがカレントで未使用の文字列ヘッダーの数。
これは利便性のために使用されるものでsizeof (char)
と同じ。
すべての文字列データの総バイト数。
長さ1のベクターのヘッダーを含めたバイトサイズ。
ベクターブロックから割り当てられたベクターブロック数。
ベクタースロットの内部的なサイズで常にsizeof (Lisp_Object)
と等しい。
全使用済みベクターのスロット数。スロット数にはプラットフォームに応じてベクターのヘッダーに由来する一部、またはすべてのオーバーヘッドが含まれるかもしれない。
すべてのベクターブロックのフリースロットの数。
浮動小数点数オブジェクトの内部的なサイズ(sizeof (struct
Lisp_Float)
)。(ネイティブプラットフォームのfloat
やdouble
と混同しないこと。)
使用中の浮動小数点数の数。
オペレーティングシステムから取得したスペースにあるがカレントで未使用の浮動小数点数の数。
インターバルオブジェクト(interval object)の内部的なサイズ(sizeof (struct interval)
)。
使用中のインターバルの数。
オペレーティングシステムから取得したスペースにあるがカレントで未使用のインターバルの数。
バッファーの内部的なサイズ(sizeof (struct
buffer)
)。(buffer-size
関数がリターンする値と混同しないこと。)
使用中のバッファーオブジェクトの数。これにはユーザーからは不可視のkillされたバッファー、つまりリストall_buffers
内のバッファーすべてが含まれる。
ヒープスペースを計る単位であり常に1024バイトと等しい。
unit-size単位での総ヒープサイズ。
unit-size単位でのカレントで未使用のヒープスペース。
純粋スペース(純粋ストレージを参照)内にオーバーフローがあり、かつEmacsが(時代遅れとなった)unexec
メソッド(Emacsのビルドを参照)を使用してダンプされていたら、この場合は実際にガーベージコレクションを行うことは不可能なのでgarbage-collect
はnil
をリターンする。
この変数が非nil
ならEmacsはガーベージコレクションの最初と最後にメッセージを表示する。デフォルト値はnil
。
これはガーベージコレクションの終わりに実行されるノーマルフック。ガーベージコレクションはこのフックの関数の実行中は抑制されるので慎重に記述すること。
この変数の値は別のガーベージコレクションをトリガーするために、ガーベージコレクション後にLispオブジェクト用に割り当てなければならないストレージのバイト数。特定のオブジェクトタイプに関する情報を取得するために、garbage-collect
がリターンした結果を使用できる。バッファーのコンテンツに割り当てられたスペースは勘定に入らない。
threshold(しきい値)の初期値はGC_DEFAULT_THRESHOLD
であり、これはalloc.c内で定義されている。これはword_size
単位で定義されているので、デフォルトの32ビット設定では400,000、64ビット設定では800,000になる。大きい値を指定するとガーベージコレクションの頻度が下る。これはガーベージコレクションにより費やされる時間を減少させる(のでガーベージコレクションが滅多に発生しないサイクル間ではLispプログラムは高速に実行されるだろう)が、メモリーの総使用量は増大する。大量のLispデータを作成するプログラムにおいて、特に高速な実行を要する場合にはこれを行いたいと思うかもしれない。ただしわたしたちは長期間に渡るthresholdの増加は推奨しないし、満足できる速さでプログラムが実行できる以上にの値には決してセットしないことをお勧める。必要以上に大きいthresholdを用いることによってシステムレベルでメモリーが逼迫する可能性があること、更にガーベージコレクションの各サイクルにより時間を要することにもなるので避けるべきである。
GC_DEFAULT_THRESHOLD
の1/10まで下げた小さな値を指定することにより、より頻繁にガーベージコレクションを発生させることができる。この最小値より小さい値は後続のガーベージコレクションで、garbage-collect
がthresholdを最小値に戻すときまでしか効果をもたないだろう。
この変数の値はガーベージコレクション発生するまでのコンス(訳注:
これはgc-cons-threshold
やgc-cons-percentage
の‘-cons-’のことで、これらの変数が定義されているalloc.c内ではLisp方言での‘cons’をより一般化したメモリー割り当てプロセスのことを指す模様)の量をカレントヒープサイズにたいする割り合いで指定する。この条件とgc-cons-threshold
を並行して適用して、条件が両方満足されたときだけガーベージコレクションが発生する。
ヒープサイズ増加にともないガーベージコレクションの処理時間は増大する。したがってガーベージコレクションの頻度割合を減らすのが望ましいことがある。
gc-cons-threshold
と同じように必要以上に増加させず、長期間増加したままにしないこと。
gc-cons-threshold
およびgc-cons-percentage
を介した制御は単なる近似です。たとえEmacsが定期的にしきい値(threshold)の枯渇をチェックしていても、効率上の理由によりヒープ、またはgc-cons-threshold
やgc-cons-percentage
の変更のそれぞれにたいして、その後即座にガーベージコレクターをトリガーする訳ではありません。更にしきい値計算の効率化のために、Emacsはヒープ内のカレントでアクセス可能なオブジェクトを計数してヒープサイズを近似します。
garbage-collect
がリターンする値はデータ型に分類されたLispデータのメモリー使用量を記述します。それとは対照的に関数memory-limit
はEmacsがカレントで使用中の総メモリー量の情報を提供します。
この関数はEmacsがカレントで使用中の仮想メモリーの総バイト数を1024で除してリターンする。あるアクションがメモリー使用にどのよな効果を及ぼすかについて概観を得るためにこの関数を使用できる。
この変数はLispオブジェクト用のメモリーが不足に近い状態ならt
、それ以外ならnil
。
これはそのEmacsセッションで作成されたオブジェクト数をカウントしたリスト。これらのカウンターはそれぞれ特定の種類のオブジェクトを数える。詳細はドキュメント文字列を参照のこと。
この関数はシステムメモリーのトータル量とフリーな量をリターンする。サポートされないシステムでは値はnil
かもしれない。
default-directory
がリモートホスト上を指している場合には、そのホストのメモリー情報がリターンされる。
この変数はそのEmacsセッションでそれまでに行われたガーベージコレクションの合計回数。
この変数はそのEmacsセッションでガーベージコレクションの間に費やされた経過時間を浮動小数点数で表した総秒数。
Emacsがどこでメモリーを使用(種々の変数、バッファー、キャッシュ)しているかが確認できれば便利なときがあるかもしれない。このコマンドはその概要を提供する(‘"*Memory Report*"’という)バッファーを新たにオープンすることに加えて、“最大”のバッファーおよび変数をリストする。
ここでのデータは変数サイズを計算する同質的な方法が究極的に存在しないために近似値である。たとえば2つの変数がデータ構造を共有するかもしれず、その場合には2回カウントされるだろうが、このコマンドは依然としてEmacsが使用する有用なメモリーの高レベル概要を与えるかもしれない。
Next: スタックに割り当てられたオブジェクト, Previous: 純粋ストレージ, Up: GNU Emacsの内部 [Contents][Index]