[Chicago-talk] neat little optimization
Jim Thomason
thomasoniii at gmail.com
Tue Oct 12 21:07:44 CDT 2004
In retrospect, this is a 'duh' optimization, but its uses are limited
enough that I guess it makes sense that I hadn't thought of it before.
One standard thing that I do fairly regularly is use objects as keys
into a hash.
sub expensive_calculation {
my $self = shift;
return $cached_calculations{$self} if defined $cached_calculations{$self};
my $calculation = $self->_expensive_calculation;
$cached_calculations{$self} = $calculation;
return $calculation;
}
(yes, for the pedantic out there, that can be written tighter and
faster, but since the expensive calculation is only done once, I
greatly prefer expanding the syntax and having it be more legible)
Literally using the object as a key into a hash. So we can do our big
expensive calculations, then cache the value based upon the memory
address of the object. Subsequent hits only require the time for a
hash lookup, not to constantly re-do the expensive calculation. Joy!
Your program leaps in speed.
But, alas, that was not good enough for me. I'm currently optimizing
Basset and wringing as much speed as I possibly can out of it. I had
one method that was much slower than I felt it should be. Inspecting
it, it was fairly straightforward, and was using the object to lookup
in a hash a lot.
sub stack {
my $self = shift;
if (@_) {
if ($_[0] == 0) {
$cached{$self} = 0;
} else {
$cached{$self} += shift;
}
$cached{$self} = 0 if $cached{$self} < 0;
}
return $cached{$self};
}
(simplified, of course)
But the point is, I was doing a lot of cache lookups using the
stringified object as the key. And then it hit me - I was using the
stringified object as the key. Why not cache it out?
sub stack {
my $self = shift;
my $key = '' . $self;
if (@_) {
if ($_[0] == 0) {
$cached{$key} = 0;
} else {
$cached{$key} += shift;
}
$cached{$key} = 0 if $cached{$key} < 0;
}
return $cached{$key};
}
Voila. The object is only stringified once, and the key is then used
for the lookup in the future. This little tidbit here yielded a 50%
speed increase (though, admittedly we're talking about going from
3,000/sec ->4,600 sec), which I was quite pleased with.
Uses? Minimal. You need a very frequently called function that does a
lot of hash lookups based upon the stringified version of the object.
If it doesn't do a lot of lookups or isn't called a hell of a lot, you
probably wouldn't even be able to measure the difference.
But for super speed critical stuff? Works like a charm.
-Jim...
More information about the Chicago-talk
mailing list