Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi All, Just wondering if there is a module or something out there in PERL that can be used to get the number of bytes in a hash, similar to the way we can use the length function for a string. Any help at all would be greatly appreciated Thanx, Val

Replies are listed 'Best First'.
Re: Function to measure size of a hash
by broquaint (Abbot) on Jul 24, 2002 at 10:46 UTC
    Just wondering if there is a module or something out there in PERL that can be used to get the number of bytes in a hash
    I'm guessing you mean the number of bytes in all the values of a hash, which you could do like so
    my %hash = qw(foo one bar two baz three); my $hash_len = 0; $hash_len += length for values %hash; print "hash length is $hash_len\n"; __output__ hash length is 11
    And make sure you use the bytes pragma if you're working with Unicode (unless you're using 5.8.0 which should deal with it seamlessly).
    HTH

    _________
    broquaint

      Good solution... however, what if it's a multi-dimensional hash? Perhaps a recursive function that'll traverse the tree and find the number of bytes in each branch and eventually return it to the top?

      However, I believer perl requires quite a few bytes extra for storing each scalar, as well as even more bytes to keep track of hash mappings, so if the purpose of this proposed chunk of code is to help work out memory constraint on a system, the value it returns will be optimistically low at best.

      "Falling in love with map, one block at a time." - simeon2000

Re: Function to measure size of a hash
by katgirl (Hermit) on Jul 24, 2002 at 10:39 UTC
    hash size

    See above for details! :) Update: Fixed the link, sorry!
      Hi,

      Try not to link like that please, it can cause users to think that they have logged out (because the domain name you use in the link could be different from the one the users cookie is for).

      A better way is to use the id:// monktag like so:

      [id://73550]
      This has the added advantage of being a bit easier to type and automatically converts to the node title name(hash size), as well as being displayed with the correct doamin name for the user.

      Cheers,

      Yves / DeMerphq
      ---
      Writing a good benchmark isnt as easy as it might look.

Re: Function to measure size of a hash
by PetaMem (Priest) on Jul 24, 2002 at 11:12 UTC
    Hi,

    I'm using this code, to get some basic informations about the central structures in a software where basically a hash structure is the top/central element:($self points to the hash)

    print "Buckets used/allocated:\t",scalar(%{$self}),"\n"; while(($key,$value) = each %$self) { $num_keys++; $num_mu += scalar(@$value); } print "\t\tNumber Words/meanings:\t$num_keys/$num_mu\n";
    The value is a pointer to an array of some data, therefore the key-value iteration. That way, you get the number of keys and the (total) number of values. (in this case)

    Bye
     PetaMem

Re: Function to measure size of a hash. (multi-dimensional example)
by gmpassos (Priest) on Jul 25, 2002 at 04:22 UTC
    Just use this 2 functions, and see the example.
    This accept multi-dimensional hash and array.

    my %H = ( a => { aaa => 111 , bbb => 222 , } , b => { ccc => 333 , ddd => 444 , } , c => [a,b,c,d, {x=>555,y=>666} , [w,w,w] ] , ); my ($keys,$vals) = HASH_size(%H) ; print "Size of keys: $keys\nSize of values: $vals\n" ; ############# # HASH_SIZE # ############# sub HASH_size { my (%hash) = @_ ; my ($KEYS_size,$VALS_size) ; foreach my $Key ( keys %hash ) { if ( ref( $hash{$Key} ) =~ /HASH/i) { $KEYS_size += length($Key) ; my ($k,$v) = &HASH_size( %{$hash{$Key}} ) ; $KEYS_size += $k ; $VALS_size += $v ; } elsif ( ref( $hash{$Key} ) =~ /ARRAY/i) { $KEYS_size += length($Key) ; my ($k,$v) = &ARRAY_size( @{$hash{$Key}} ) ; $KEYS_size += $k ; $VALS_size += $v ; } else { $KEYS_size += length($Key) ; $VALS_size += length($hash{$Key}) ; } } return($KEYS_size,$VALS_size) ; } ############## # ARRAY_SIZE # ############## sub ARRAY_size { my ( @array ) = @_ ; my ($KEYS_size,$VALS_size) ; for(0..$#array) { if (ref(@array[$_]) =~ /ARRAY/i) { my ($k,$v) = &ARRAY_size( @{@array[$_]} ) ; $KEYS_size += $k ; $VALS_size += $v ; } elsif (ref(@array[$_]) =~ /HASH/i) { my ($k,$v) = &HASH_size( %{@array[$_]} ) ; $KEYS_size += $k ; $VALS_size += $v ; } else {$VALS_size += length(@array[$_]) ;} } return( $KEYS_size,$VALS_size ) ; }

    "The creativity is the expression of the liberty".
Re: Function to measure size of a hash
by jsegal (Friar) on Jul 24, 2002 at 18:10 UTC
    In Tie::Cache, there is a (private) method _get_data_length, which tries to estimate the total memory used by a HASH, SCALAR, or ARRAY. It recursively traverses the structure, adds a guess of the overhead needed, and uses the length function to determine "content" length. You might be able to use this function to come close, or use it as a springboard to writing your own.

    --JAS