Fastest way to check for an empty hash in Perl?

Recently motivated out of curiosity, I and a coworker were benchmarking different approaches to determining if a hash is empty in Perl. Expanding on this a little I present these curious results. In summary, it seems that there are roughly two code paths we’re hitting here. One for if (scalar %hash) and if (%hash), and another for if (keys %hash), if (values %hash), if (scalar keys %hash), and if (scalar values %hash). The latter is much faster when you hit a non-empty hash. It feels somewhat unfortunate that the simplest approach is (approximately) slowest.

hash size: 0
                      Rate if_scalar  if if_values if_keys if_scalar_values if_scalar_keys
if_scalar        3125000/s        -- -3%      -21%    -23%             -24%           -24%
if               3205128/s        3%  --      -19%    -21%             -22%           -22%
if_values        3937008/s       26% 23%        --     -2%              -4%            -5%
if_keys          4032258/s       29% 26%        2%      --              -2%            -2%
if_scalar_values 4098361/s       31% 28%        4%      2%               --            -1%
if_scalar_keys   4132231/s       32% 29%        5%      2%               1%             --
hash size: 3
                      Rate if_scalar   if if_keys if_scalar_keys if_values if_scalar_values
if_scalar         967118/s        --  -1%    -86%           -87%      -87%             -88%
if                978474/s        1%   --    -86%           -86%      -87%             -88%
if_keys          7142857/s      639% 630%      --            -1%       -7%             -10%
if_scalar_keys   7246377/s      649% 641%      1%             --       -6%              -9%
if_values        7692308/s      695% 686%      8%             6%        --              -3%
if_scalar_values 7936508/s      721% 711%     11%            10%        3%               --
hash size: 500
                      Rate   if if_scalar if_scalar_values if_values if_scalar_keys if_keys
if                912409/s   --       -2%             -88%      -88%           -88%    -88%
if_scalar         927644/s   2%        --             -87%      -88%           -88%    -88%
if_scalar_values 7352941/s 706%      693%               --       -1%            -4%     -4%
if_values        7462687/s 718%      704%               1%        --            -3%     -3%
if_scalar_keys   7692308/s 743%      729%               5%        3%             --     -0%
if_keys          7692308/s 743%      729%               5%        3%             0%      --

From the script:

#!/usr/bin/env perl

use strict;
use warnings;
use Benchmark qw(cmpthese);

my %hash_empty = ();
my %hash_small = (1..6);
my %hash_large = (1..1000);

foreach my $ref (\%hash_empty, \%hash_small, \%hash_large) {
  print 'hash size: ' . scalar(keys(%$ref)) . "\n";
  cmpthese(5_000_000, {
    if => sub { if (%$ref) { 1 } else { 0 } },
    if_scalar => sub { if (scalar %$ref) { 1 } else { 0 } },
    if_keys => sub { if (keys %$ref) { 1 } else { 0 } },
    if_values => sub { if (values %$ref) { 1 } else { 0 } },
    if_scalar_keys => sub { if (scalar keys %$ref) { 1 } else { 0 } },
    if_scalar_keys => sub { if (scalar keys %$ref) { 1 } else { 0 } },
    if_scalar_values => sub { if (scalar values %$ref) { 1 } else { 0 } },
  });
}

No obvious advantage to buying things from target.com versus other online retailers

I bought a window air conditioner from target.com, primarly because if I was told I could return it in a local store.

Last Friday (May 11) it arrived, and it was the right tracking number, but it was actually a microwave oven. Was busy with the new house last weekend and with our cat’s health problems (he’s doing much better now.)

So, this Friday (May 18), we decided to return it in the store nearby. Turns out, in this case, their claim that you can return it locally is a lie, they won’t do that if they shipped you the wrong item — and we confirmed this after calling their 800 number and requesting a return (which I’ll have to drop off at UPS sometime after labeling it.) To add insult to injury, the shipping label page doesn’t load completely (tried with multiple browsers/OSes), and we’re going to have to call them up again.

The one reason I chose them over Amazon, or a couple of much better online retailers for buying small appliances was that I was told I could return it in store, so this is why I will be telling everyone I know not to buy things online from Target. It seems that when “brick-and-mortar” retailers get into online retail, they do a very poor job of integrating both operations. This is somewhat understandable if you think about the business. However, as a customer, you either shouldn’t have to care about such things, or they should be explicit about all the common cases where the return in store is impossible. If they are really trying to provide some benefit over pure-online retailers, they’re failing at that.

(Edit: We finally did get a valid shipping label out of them, shipped it back, and I was credited. Ended up just buying the air conditioner from some random retailer that lists their stuff on Amazon.)

Now with IPv6

Moved my web stuff around, now this has IPv6.

I’m still here

I’ve become disillusioned with the constant churn of websites-controlled-by-other-entities which I’m somehow compelled to participate in. They’ve developed a very effective value proposition for introverts like me who are otherwise likely to lose contact with friends over time, but I really tire of it being a constant cycle of replacing one proprietary system with another. I know I tend to use Google Plus more than the others, but there are people I know who I’ve never seen on there. And then there’s the offensive way in which some of the most successful of these insist on “real” names. Not that I’m bothered by “sticky” identities with reputation, nor do I even mind using my “real” name that much, but it is quite a break with the traditional internet culture I value.

I’m toying with the idea of setting up my own Diaspora “pod”. They’re one of the first things since email and Jabber that gets the model somewhat right — not in the control of a single entity[*], based on a loose federation of independent agents. Part of what bothers me about the proprietary services is that I start to feel that I’ve left pieces of myself cluttered all over — kind of the disconcerting feeling you might have when you’ve left physical possessions behind in the real world.

[*] Okay, you can argue that the DNS is subject to some autocratic control, and you’re even largely right, though there are some workable proposals for decentralizing that (Namecoin, etc.)

My 3 most used pairs of headphones

  1. Sony MDR-V600 I bought back around 1999. I used these constantly until the hinge on the headband failed after 5 or 6 years. The earpads were significantly trashed at that point.
  2. Some unidentifiable earbuds that came with a cheap Sandisk MP3 player I bought on Woot. I’ve used them fairly regularly for the past 4 years, they sound okay for little earbuds, they don’t cause me discomfort, and they are useful when it’s too warm to have closed-ear cans over my ears without getting annoyingly sweaty. Strangely durable too.
  3. Sennheiser HD 280 pro (64 Ω). I’ve had these for 4 years or so, they’ve been my replacement for the MDR-V600, and they’re what I tell anyone to buy who wants a decent pair of headphones for about a hundred bucks. The only downside is that if I’m having a little bit of sinus trouble, I find I like to be sure to adjust them so most of the ample tension is on the cranium, not on the soft tissues. I’ve replaced the ear pads once on them, but the rest is still in great condition.

I think that if you’re going to spend more than $10 on headphones, they might as well make music sound really good. Those headphones with the band that goes behind the head are just for folks that are afraid to mess up their hair.