Devel-Size-0.58 > Devel::Size

名前

Devel::Size - Perl変数のメモリ使用量を調べる

概要

  use Devel::Size qw(size total_size);

  my $size = size("A string");

  my @foo = (1, 2, 3, 4, 5);
  my $other_size = size(\@foo);

  my $foo = {a => [1, 2, 3],
          b => {a => [1, 3, 4]}
         };
  my  $total_size = total_size($foo);

説明

This module figures out the real sizes of Perl variables in bytes. Call functions with a reference to the variable you want the size of. If the variable is a plain scalar it returns the size of the scalar. If the variable is a hash or an array, use a reference when calling.

このモジュールはPerl変数の実際のサイズをバイト単位で計算する。その サイズを知りたい変数へのリファレンスを与えて関数を呼ぶ。その変数が 単なるスカラーであるなら、そのスカラーのサイズを返す。その変数が ハッシュや配列であるなら、呼び出し時にリファレンスを利用する。

関数

size($ref)

The size function returns the amount of memory the variable returns. If the variable is a hash or an array, it only reports the amount used by the structure, not the contents.

size関数は、その変数が返すメモリ量を返す。変数がハッシュか 配列であるなら、その構造によって使用されているメモリ量だけを 報告し、コンテンツが使用しているメモリ量は報告しない。

total_size($ref)

The total_size function will traverse the variable and look at the sizes of contents. Any references contained in the variable will also be followed, so this function can be used to get the total size of a multidimensional data structure. At the moment there is no way to get the size of an array or a hash and its elements without using this function.

total_size関数は、変数を辿ってそのコンテンツのサイズを調べる。 変数内に含まれるリファレンスもフォローされる。よって、この関数を使って 多次元データ構造の全サイズを得られる。当座のところ、配列やハッシュと それらの要素のサイズを得るには、この関数を使うより他ない。

エクスポート

None but default, but optionally size and total_size.

デフォルトでは何もエクスポートせず、sizetotal_sizeを選択できる。

メモリアロケーションの理解

Please note that the following discussion of memory allocation in perl is based on the perl 5.8.0 sources. While this is generally applicable to all versions of perl, some of the gory details are omitted. It also makes some presumptions on how your system memory allocator works so, while it will be generally correct, it may not exactly reflect your system. (Generally the only issue is the size of the constant values we'll talk about, not their existence)

以下のperlにおけるメモリアロケーションの議論はperl 5.8.0のソースに 基づいていることに注意されたし。一般的にはperlの全バージョンで適用 可能であるとしても、細部のいくつかは割愛している。また、あなたの システムのメモリアロケーターの動作を仮定しており、一般的にそれが 正しくても、正確にはシステムを反映していないかもしれない(一般的に唯一の 関心事は我々が語っている定数変数のサイズであって、それらの存在ではない)。

Cライブラリ

It's important firtst to understand how your OS and libraries handle memory. When the perl interpreter needs some memory, it asks the C runtime library for it, using the malloc() call. malloc has one parameter, the size of the memory allocation you want, and returns a pointer to that memory. malloc also makes sure that the pointer it returns to you is properly aligned. When you're done with the memory you hand it back to the library with the free() call. free has one parameter, the pointer that malloc returned. There are a couple of interesting ramifications to this.

まず重要なことは、あなたの使っているOSとライブラリがどのようにメモリを 取り扱うかのかを知ることだ。perlインタプリタは、メモリが必要になると malloc()の呼び出しを利用して、Cのランタイムライブラリにそれを要求する。 mallocは一つの引数、必要とするメモリアロケーションサイズをとり、 そのメモリのポインタを返す。また、mallocは返されたそのポインタが 適切に整列されていることを保証する。メモリを処理したらあなたは free()を呼び出してポインタをライブラリに返す。freeは一つの 引数、mallocが返したポインタをとる。ここから派生する二つの興味深い ことがある。

Because malloc has to return an aligned pointer, it will round up the memory allocation to make sure that the memory it returns is aligned right. What that alignment is depends on your CPU, OS, and compiler settings, but things are generally aligned to either a 4 or 8 byte boundary. That means that if you ask for 1 byte, malloc will silently round up to either 4 or 8 bytes, though it doesn't tell the program making the request, so the extra memory can't be used.

mallocは調整されたポインタを返さなければならないので、メモリアロケーションを 行ってメモリが適切に整列されるようにする。この調整は、一般的に4ないし 8バイト境界のいずれかに整列されることを除いて、あなたの使うマシンのCPU、OS、 コンパイラ環境に依存する。これはつまり、もしあなたが1バイトを要求 しても、mallocは要求しているプログラムに何も伝えずに黙って4ないしは 8バイトのいずれかを処理し、それゆえ余分なメモリは使えないことを意味する。

Since free isn't given the size of the memory chunk you're freeing, it has to track it another way. Most libraries do this by tacking on a length field just before the memory it hands to your program. (It's put before the beginning rather than after the end because it's less likely to get mangled by program bugs) This size field is the size of your platform integer, Generally either 4 or 8 bytes.

freeにはあなたが解放しようとしているメモリチャンクのサイズを与えられて いないので、別の方法でサイズを追わなければならない。ほとんどのライブラリは あなたのプログラムで利用されるメモリの直前に、レンクス領域を付けることで これを行なう(この領域を後ろではなく前に置くのは、プログラムのバグで 領域がめちゃくちゃにされにくくするためである)。この領域の大きさは、 あなたが使うプラットフォームの整数サイズ、一般的には4ないし8バイトである。

So, if you asked for 1 byte, malloc would build something like this:

つまり、もしあなたが1バイトを要求したとすると、mallocは次のように構築する:

     +------------------+
     | 4 byte length    |
     +------------------+ <----- mallocが返したポインタ
     | your 1 byte      |
     +------------------+
     | 3 bytes padding  |
     +------------------+

As you can see, you asked for 1 byte but malloc used 8. If your integers were 8 bytes rather than 4, malloc would have used 16 bytes to satisfy your 1 byte request.

ご覧のとおり、あなたは1バイトを要求したが、mallocは8バイト使っている。 もしお使いのマシンの整数が4バイトではなく8バイトであるなら、mallocは あなたの1バイトの要求を満たすために16バイトを使うことだろう。

The C memory allocation system also keeps a list of free memory chunks, so it can recycle freed memory. For performance reasons, some C memory allocation systems put a limit to the number of free segments that are on the free list, or only search through a small number of memory chunks waiting to be recycled before just allocating more memory from the system.

Cのメモリアロケーションシステムはまた、解放されているメモリチャンクの リストを保持しており、それにより解放されたメモリを再利用する。パフォーマンス 上の理由から、Cのメモリアロケーションシステムのあるものは、フリーリストに ある解放されたセグメントの数に制限を課している。あるいは、システムから より多くのメモリをアロケートする前に、再利用のために待機している小数の メモリチャンクを調べるだけになっている。

The memory allocation system tries to keep as few chunks on the free list as possible. It does this by trying to notice if there are two adjacent chunks of memory on the free list and, if there are, coalescing them into a single larger chunk. This works pretty well, but there are ways to have a lot of memory on the free list yet still not have anything that can be allocated. If a program allocates one million eight-byte chunks, for example, then frees every other chunk, there will be four million bytes of memory on the free list, but none of that memory can be handed out to satisfy a request for 10 bytes. This is what's referred to as a fragmented free list, and can be one reason why your program could have a lot of free memory yet still not be able to allocate more, or have a huge process size and still have almost no memory actually allocated to the program running.

メモリアロケーションシステムは、可能な限り少ない数のチャンクをフリーリスト に保持しようとする。これは、リスト上に隣接する二つのメモリチャンクがあるか どうかに着目し、もしあるなら、それらを連結してより大きな一つのチャンクに まとめることによってなされる。これは非常にうまいやり方だが、フリーリスト上 には大量のメモリがあるのに、アロケートすることができないという事態が起こる。 例えば、あるプログラムが100万個の8バイトチャンクをアロケートしたとすると、 チャンク毎に解放されて、リスト上には400万バイトがあることになる。だが そのメモリのいずれも、10バイトの要求を満たすための配分を行えない。 これが断片化されたフリーリストとして言及されるものだ。そしてこれが、 あなたのプログラムがフリーのメモリをたくさん持っているにもかかわらず、 それ以上アロケートできなくなったり、巨大なプロセスサイズがあるのに、 プログラムを実行するためにアロケートするメモリがほとんどないといった 理由の一つとなりうる。

Perl

Perl's memory allocation scheme is a bit convoluted, and more complex than can really be addressed here, but there is one common spot where perl's memory allocation is unintuitive, and that's for hash keys.

Perlのメモリアロケーションシステムは、いま少し入り組んでいる。そして ここで実際述べうる以上に複雑だ。しかし、perlのメモリアロケーションが 非直感的である一つの共通点がある。それはハッシュのキーに関してだ。

When you have a hash, each entry has a structure that points to the key and the value for that entry. The value is just a pointer to the scalar in the entry, and doesn't take up any special amount of memory. The key structure holds the hash value for the key, the key length, and the key string. (The entry and key structures are separate so perl can potentially share keys across multiple hashes)

ハッシュでは、各エントリ毎に、キーとそのエントリ値を指し示す構造を 持っている。値とは、そのエントリ内にあるスカラーへの単なるポインタだ。 メモリを特別消費するわけではない。キー構造は、そのキーに対するハッシュ値、 キー長、そしてキー文字列を持つ(エントリとキーの構造は分けられているので perlは潜在的に複数のハッシュ間でキーを共有可能だ)。

The entry structure has three pointers in it, and takes up either 12 or 24 bytes, depending on whether you're on a 32 bit or 64 bit system. Since these structures are of fixed size, perl can keep a big pool of them internally (generally called an arena) so it doesn't have to allocate memory for each one.

エントリ構造はその中に三つのポインタを持ち、それぞれは12ないし24バイトの いずれかをとる。これはあなたが32bitシステムか64bitシステムを使うかに依存 している。これらの構造は固定した大きさなので、perlは内部でそれらの巨大な プール(一般的にarenaと呼ばれる)を維持できる。それゆえ、その都度メモリ アロケートする必要はない。

The key structure, though, is of variable length because the key string is of variable length, so perl has to ask the system for a memory allocation for each key. The base size of this structure is 8 or 16 bytes (once again, depending on whether you're on a 32 bit or 64 bit system) plus the string length plus two bytes.

だがキー構造は可変長である。というのも、キーの文字列が可変長であり、 それゆえperlはそれぞれのキー毎に、メモリアロケーションをシステムに 要求しなければならないからだ。この構造の基本的な大きさは、8ないしは 16バイト(繰り返すが、システムが16bitか32bitかに依存する)プラス 文字列の長さプラス2バイトである。

Since this memory has to be allocated from the system there's the malloc size-field overhead (4 or 8 bytes) plus the alignment bytes (0 to 7, depending on your system and the key length) that get added on to the chunk perl requests. If the key is only 1 character, and you're on a 32 bit system, the allocation will be 16 bytes. If the key is 7 characters then the allocation is 24 bytes on a 32 bit system. If you're on a 64 bit system the numbers get even larger.

このメモリはシステムからアロケートされなければならないので、mallocの サイズ領域のオーバーヘッド+アラインメントのバイト(0〜7で、システムと キー長に依存する)が発生し、perlが要求したチャンクに追加される。もし キーがただ1キャラクタ分で、システムが32bitであるなら、アロケーションは 16バイトになる。キーが7キャラクタ分であるなら、アロケーションは32bit システム上で24バイトになる。もし64bitシステム上であるなら、その数は さらに大きくなる。

This does mean that hashes eat up a lot of memory, both in memory Devel::Size can track (the memory actually in the structures and strings) and that it can't (the malloc alignment and length overhead).

これはつまり、Devel::Sizeが追えるメモリ(構造と文字列内の実際のメモリ)と、 追うことのできないメモリ(mallocのアラインメントと長さのオーバーヘッド)の 両方において、ハッシュは大量のメモリを喰うということだ。

危険

Devel::Size, because of the way it works, can consume a considerable amount of memory as it runs. It will use five pointers, two integers, and two bytes worth of storage, plus potential alignment and bucket overhead, per thing it looks at. This memory is released at the end, but it may fragment your free pool, and will definitely expand your process' memory footprint.

Devel::Sizeは、その動作方法からして、実行のためにかなり大量のメモリを 消費する可能性がある。一つのものを調べるのにつき、5つのポインタ、 2つの整数、そしてストレージするために2バイトを使う。加えて、潜在的な アラインメントとバケットのオーバーヘッドがある。このメモリは最終的に 解放されるが、フリープールを断片かするかもしれない。そして プロセスのメモリ占有スペースを明らかに拡大するだろう。

バグ

Doesn't currently walk all the bits for code refs, formats, and IO. Those throw a warning, but a minimum size for them is returned.

現在のところ、コードリファレンス、フォーマット、そしてIOのbitを全て まわることはない。これらは警告を投げ、それらの最小サイズが返される。

Devel::Size only counts the memory that perl actually allocates. It doesn't count 'dark' memory--memory that is lost due to fragmented free lists, allocation alignments, or C library overhead.

Devel::Sizeはperlが実際にアロケートしたメモリのみをカウントする。 '暗黒'メモリ --断片化したフリーリスト、アロケーションのアラインメント、 あるいはCライブラリのオーバーヘッドによって失われたメモリ-- はカウントしない。

作者

Dan Sugalski [email protected]

参考

perl(1).