! /usr/bin/perl -w use strict; my %h = ( a => 1, b => undef, c => 1, d => 1, e => undef, ); my @def; $def[ defined $_ ? 1 : 0]++ for values %h; print "undefined=$def[0], defined=$def[1]\n"; __END__ produces: undefined=2, defined=3 #### #! /usr/bin/perl -w use strict; use Benchmark qw/cmpthese/; my %h; my $nr = shift || 10000000; $h{$nr} = ((rand() > 0.2) ? 1 : undef) while $nr--; sub by_for { my $h = shift; my @def; $def[ defined $_ ? 1 : 0]++ for values %$h; @def; } sub by_grep { my $h = shift; ( scalar (grep !defined, values %$h), scalar (grep defined, values %$h), ); } printf "by_for: undefined=%d, defined=%d\n", by_for( \%h ); printf "by_grep: undefined=%d, defined=%d\n", by_grep( \%h ); cmpthese( -5, { for => ' by_for( \%h ) ', grep => ' by_grep( \%h ) ', } ); #### by_for: undefined=2000300, defined=7999700 by_grep: undefined=2000300, defined=7999700 Benchmark: running for, grep for at least 5 CPU seconds... for: 5 wallclock secs ( 5.27 usr + 0.00 sys = 5.27 CPU) @ 163521.04/s (n=862318) grep: 6 wallclock secs ( 5.05 usr + 0.00 sys = 5.05 CPU) @ 224222.12/s (n=1131621) Rate for grep for 163521/s -- -27% grep 224222/s 37% -- #### cmpthese( -300, { byfor => sub { by_for( \%h ) }, bygrep => sub { by_grep( \%h ) }, } ); #### by_for: undefined=2398233, defined=9601767 by_grep: undefined=2398233, defined=9601767 Benchmark: running byfor, bygrep for at least 300 CPU seconds... byfor: 311 wallclock secs (311.09 usr + 0.03 sys = 311.12 CPU) @ 0.06/s (n=20) bygrep: 313 wallclock secs (312.95 usr + 0.04 sys = 312.99 CPU) @ 0.04/s (n=13) s/iter bygrep byfor bygrep 24.1 -- -35% byfor 15.6 55% -- #### sub by_diff { my $h = shift; my $defined = grep defined, values %$h; ( scalar keys(%$h) - $defined, $defined, ); } printf "by_for: undefined=%d, defined=%d\n", by_for( \%h ); printf "by_grep: undefined=%d, defined=%d\n", by_grep( \%h ); printf "by_diff: undefined=%d, defined=%d\n", by_diff( \%h ); cmpthese( -600, { byfor => sub { by_for( \%h ) }, bygrep => sub { by_grep( \%h ) }, bydiff => sub { by_diff( \%h ) }, } ); #### by_for: undefined=2398740, defined=9601260 by_grep: undefined=2398740, defined=9601260 by_diff: undefined=2398740, defined=9601260 Benchmark: running bydiff, byfor, bygrep for at least 600 CPU seconds... bydiff: 606 wallclock secs (604.93 usr + 0.11 sys = 605.04 CPU) @ 0.08/s (n=51) byfor: 625 wallclock secs (623.32 usr + 0.09 sys = 623.41 CPU) @ 0.06/s (n=40) bygrep: 604 wallclock secs (602.22 usr + 0.07 sys = 602.29 CPU) @ 0.04/s (n=25) s/iter bygrep byfor bydiff bygrep 24.1 -- -35% -51% byfor 15.6 55% -- -24% bydiff 11.9 103% 31% --