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);
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 this scalar. If the variable is a hash or an array, use a reference when calling.
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.
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.
So, if you asked for 1 byte, malloc would build something like this:
+------------------+ | 4 byte length | +------------------+ <----- the pointer malloc returns | 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.
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.
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.
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)
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.
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.
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.
Besides saving a lot of memory, this change means that Devel::Size runs significantly faster than previous versions.
These may be disabled by setting
$Devel::Size::warn = 0
MSVC provides exception handling able to deal with this possibility, and when built with MSVC Devel::Size will now attempt to ignore (or log) them and continue. These messages are mainly of interest to Devel::Size and core developers, and so are disabled by default.
They may be enabled by setting
$Devel::Size::dangle = 0
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.
Small portion taken from the B module as shipped with perl 5.6.2.
Previously maintained by Tels <http://bloodgate.com>
New pointer tracking & exception handling for 0.72 by BrowserUK
Currently maintained by Nicholas Clark
This module is free software; you can redistribute it and/or modify it under the same terms as Perl v5.8.8.