NAME
String::Lookup - convert strings to ID's authoritatively and vice-versa
SYNOPSIS
use String::Lookup;
tie my %lookup, 'String::Lookup',
init => sub { }, # code to initialize hash with
flush => sub { }, # code to flush hash with
};
my $id= $lookup{ \$string }; # strings must be indicated by reference
my $string= $lookup{$id}; # numbers indicat id -> string mapping
# optimizing by bypassing the slow tie interface
my $ro_lookup= %lookup;
my $id= $ro_lookup->{$string} // $lookup{ \$string };
VERSION
This documentation describes version 0.01.
DESCRIPTION
Provide a simple way to map (a great number of) strings to ID's authoritatively. Uses the tie
interface for simplicity. Looking up the ID of a string is accomplished by passing a reference to the string as the key in the tied hash. If a reference is seen, it is assumed this is a string -> ID lookup (even if the string only consists of a number). If a non-reference is passed, then it is assumed to be the numeric ID for which the string should be returned.
INITIALIZATION
tie my %lookup, 'String::Lookup',
init => sub { return $hash_ref }, # code to initialize hash with
};
The init
parameter indicates a code reference that will be called to initialize the lookup hash. The subroutine is supposed to return a hash reference that should be used as the underlying hash in which string to numerical ID mapping is stored.
A simple implementation, that assumes strings will never contain newlines, could be:
sub simple_init {
my %hash;
open my $handle, '<', 'file.lookup' or die $!;
while ( <$handle> ) {
my ( $id, $string )= split ':', $_, 2;
$hash{$id}= $string;
}
close $handle;
return \%hash;
} #simple_init
FLUSHING
tie my %lookup, 'String::Lookup',
flush => sub { my ( $strings, $ids )= @_ }, # code to flush hash with
};
The flush
parameter indicates a code reference that will be called to save strings that have been added since the hash was created / initialized, or the previous time the tied hash was flushed. By default, the hash is only flushed when being untie
d, or when the tied hash is destroyed.
It is supposed to accept two parameters:
- 1 list reference for id -> string mapping
-
The first parameter is a list reference to the underlying array that is used for the ID to string mapping.
- 2 list reference to ID's that were added
-
The second parameter is a list reference to the numeric ID's that were added since the last flush (if any).
A simple implementation, that assumes strings will never contain newlines, could be:
sub simple_flush {
my ( $strings, $ids )= @_;
open my $handle, '>>', 'file.lookup' or die $!;
print $handle, "$_:$strings->[$_]\n" foreach @{$ids};
close $handle;
} #simple_flush
OPTIMIZING STRING LOOKUPS
# optimizing by bypassing the slow tie interface if possible
my $ro_lookup= %lookup;
my $id= $ro_lookup->{$string} // $lookup{ \$string };
The tie
interface is notoriously slow. If a high number of strings needs to be looked up, then the lookups may slow things down a lot. Since we only want to lookup strings because they occur again and again, it makes sense to not have to use the tie
interface if the string has already an ID assigned to it. But the underlying hash lookup is hidden by the tie
interface. If it would be possible to access the underlying (real) hash, then that could be used to first check if a string is already known.
Finding out what the underlying real hash is, is possible by accessing the tied hash in scalar context once: it will then return a reference to the underlying hash, allowing direct lookup access. Like so:
my $ro_lookup= %lookup;
If there is no defined value returned from the underlying hash, then the original, tied hash access should be used to automatically obtain the numeric ID. Like so:
my $id= $ro_lookup->{$string} // $lookup{ \$string };
Please note that the lookup in the underlying hash should be made with the string, and the lookup in the tied hash with the reference to the string!
BACKGROUND
At a former $client, a large amount of (similar) string data is processed every second. Think user agent strings, IPv4 and IPv6 numbers, URL's, tags and labels, domain names, HTTP input headers, affiliate ID's, etc. etc.
To reduce the database I/O, all of these strings are converted to numeric ID's. ID's can be smaller, and more easily packed than strings. But if a database is being used to assign numeric ID's (usually using an auto-increment feature), this means overhead. Overhead that is generally not needed for what is basically either a hash lookup, or an index on an array. This would be different if we could have a daemon like process whose function it would only be to assign numeric ID's to strings without needing a database backend.
This module provides the basic interface mechanism for such a daemon.
IMPLEMENTATION
At the moment there is only a pure Perl reference implementation available. This has the disadvantage of being slower than it could possibly be made. But it works now. It is the intention of providing a faster XS interface at a later point in time.
REQUIRED MODULES
(none)
AUTHOR
Elizabeth Mattijsen
COPYRIGHT
Copyright (c) 2012 Elizabeth Mattijsen <liz@dijkmat.nl>. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.