http://www.perlmonks.org?node_id=187293

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

I know that where efficiency is concerned it is better to pass references instead of hashes or arrays. My question is about the following code:
use strict; use warnings; use mylib; my $hashref = mylib::load_hash('big.file'); my %hash = %{$hashref};
Does the assignment in the last line of code populate the hash (thus eliminating any benefits gained from using the hashref)? I know that I can use  $$hashref{$_} or other forms of dereferencing but I'd prefer to use %hash if it's not too costly. Thanks.

Replies are listed 'Best First'.
Re: Hash references and efficiency
by jsprat (Curate) on Aug 03, 2002 at 04:41 UTC
    Yes, it populates the hash. You are dereferencing the original hashref, creating a copy and assigning it to a new hash.

    If you don't like typing curly brackets, try the arrow syntax ($hashref->{key}). BTW, treating a hashref differently than a regular hash can be considered a good thing when you review old code.

      I've actually always coded like this:

      my %hash = ( jim => 'fred', babs => 'buster' ); my $href = \%hash; print $$href{jim}, "\n";

      But you're saying that the $href->{jim} syntax is preferred?

      --
      perl -e "print qq/just another perl hacker who doesn't grok japh\n/"
      simeon2000|http://holdren.net/

        Why are you doing it like that? There's no reason to use a hashref in the above code. Use refs for complex data structures or for passing hashes and arrays back and forth between subs.
Re: Hash references and efficiency
by Cine (Friar) on Aug 03, 2002 at 09:21 UTC
    These kinds of questions are always best answered using a benchmark ;)
    #!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); sub returnhashref { my %a=(); for (1 .. 1000) { $a{$_}=$_; } return \%a; } cmpthese(-3,{ 'Ref' => sub { my $a=returnhashref(); return $$a{245}}, 'newhash' => sub { my $a=returnhashref(); my %a = %$a; return +$a{245}}});
    Benchmark: running Ref, newhash, each for at least 3 CPU seconds... Ref: 3 wallclock secs ( 3.24 usr + 0.01 sys = 3.25 CPU) @ 38 +1.54/s (n=1240) newhash: 3 wallclock secs ( 3.21 usr + 0.00 sys = 3.21 CPU) @ 21 +1.84/s (n=680) Rate newhash Ref newhash 212/s -- -44% Ref 382/s 80% --
    So using the ref is about 50% faster in this case. Btw. the easiest way of dereferencing is using the shortcut $$a{somekey} instead of $a->{somekey}

    T I M T O W T D I
      These kinds of questions are always best answered using a benchmark ;)

      Um, no offense, but no they aren't. This sort of question is best answered by considering code readability, and maybe memory usage. The odds that this is going to be a performance bottleneck in any real application are slim to none. Don't be a slave to Benchmark.

Re: Hash references and efficiency
by jlongino (Parson) on Aug 08, 2002 at 16:43 UTC
    Although your original question was answered, no one seemed to address the fact that if you code with a little planning, you can preserve efficiency and use %hash for all of your non-module code.

    Generally people write modules for whatever purpose and then only occasionally (if ever) go back and modify them. So use the references in the module and once it's finished, you can write as many programs as you like using %hash and still have efficient code. Here is an example module:

    package mylib; use strict; use warnings; use Exporter; use vars qw(@ISA @EXPORT); @ISA = qw(Exporter); @EXPORT = qw( load_hash ); sub mylib::load_hash { my $href = shift; for (1..1000) { $$href{$_} = $_; } }
    And an example program that uses it:
    #!/usr/local/bin/perl use strict; use warnings; use mylib; my %hash; mylib::load_hash(\%hash); for (keys %hash) { print "key: $_ value: $hash{$_}\n"; }

    --Jim