in reply to Re^7: Avoid Locking Entire Hashes
in thread Avoid Locking Entire Hashes

Indeed, but the final death knell is that using a mirror structure of individual sems is 3 times slower than locking the entire hash!

Lock the hash:

#! perl -slw use strict; use Data::Dump qw[ pp ]; use Time::HiRes qw[ time ]; use List::Util qw[ shuffle ]; use threads; use threads::shared; our $START //= 'aaa'; our $END //= 'zzz'; my %hash :shared = map{ $_ => 0 } $START .. $END; my $start = time; $_->join for map{ async{ my @order; { lock %hash; @order = shuffle keys %hash; } for ( @order ) { lock %hash; ++$hash{ $_ }; } } } 1 .. 4; printf "Lock hash took %.3f seconds\n", time() - $start; my @fails = grep $_ != 4, values %hash; warn @fails . " fails\n" if @fails; __END__ C:\test>909437-1 Lock hash took 1.093 seconds

Locking scalars:

#! perl -slw use strict; use Data::Dump qw[ pp ]; use Time::HiRes qw[ time ]; use List::Util qw[ shuffle ]; use threads; use threads::shared; our $START //= 'aaa'; our $END //= 'zzz'; my %sems :shared = map{ my $n :shared = 0; $_ => \$n } $START .. $END; my %hash :shared = map{ $_ => 0 } $START .. $END; my $start = time; $_->join for map{ async{ my @order; { lock %hash; @order = shuffle keys %hash; } for ( @order ) { lock ${ $sems{ $_ } }; ++$hash{ $_ }; } } } 1 .. 4; printf "Lock scalars ref took %.3f seconds\n", time() - $start; my @fails = grep $_ != 4, values %hash; warn @fails . " fails\n" if @fails; __END__ C:\test>909437-3 Lock scalars ref took 4.667 seconds

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^9: Avoid Locking Entire Hashes
by ikegami (Patriarch) on Jun 15, 2011 at 05:14 UTC
    Indeed. I recognised that your solution is better as soon as I saw it, at laest in terms of memory usage. For short locks, it's equally slow compared to locking the whole hash, though.
    >perl ikegami.pl Lock scalars ref took 1.648 seconds >perl ikegami.pl Lock scalars ref took 1.714 seconds >perl ikegami.pl Lock scalars ref took 1.702 seconds >perl browseruk.pl Lock scalars ref took 1.731 seconds >perl browseruk.pl Lock scalars ref took 1.543 seconds >perl browseruk.pl Lock scalars ref took 1.601 seconds
      it's equally slow compared to locking the whole hash, though.

      Hm. How many cores do you have?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Oh, you're surprised my slow results are much faster than yours. Core i7 720QM @ 1.66MHz (a quad core), 64-bit Windows 7 Pro, 32-bit ActivePerl 5.14. Here are my full hash locking figures:

        >perl a.pl Lock hash took 0.724 seconds >perl a.pl Lock hash took 0.750 seconds >perl a.pl Lock hash took 0.619 seconds

        4. (Upd: 8 visible cores due to hyperthreading )

        I don't understand the... surprise? To be clear, that's

        # ikegami lock ${ $mutexes{$k} }; ++$hash{$k};
        vs
        # browseruk lock ${ $hash{$k} }; ++${ $hash{$k} };

        (with proper initialisation)