I concur with salva. Once you expand your ranges and store them sorted in a packed binary file, lookup via binary search are very fast.
I generated a file of 125,000 ips (an average of 125 allocated to each of 1000 users).
Single lookups with a cold cache take about 1/100th of a second, which is probably quicker than you could load the file of ranges and populate a hash:
C:\test>echo 92.103.2.204 | 874413.pl
92.103.2.204 allocated to user;552
1 lookups (1 found) in 0.011 seconds (0.011339/sec)
C:\test>echo 63.203.110.110 | 874413.pl
63.203.110.110 allocated to user;532
1 lookups (1 found) in 0.012 seconds (0.012047/sec)
C:\test>echo 109.224.107.185 | 874413.pl
109.224.107.185 allocated to user;139
1 lookups (1 found) in 0.012 seconds (0.012018/sec)
C:\test>echo 122.228.116.36 | 874413.pl
122.228.116.36 allocated to user;485
1 lookups (1 found) in 0.013 seconds (0.012670/sec)
C:\test>echo 0.0.0.0 | 874413.pl
1 lookups (0 found) in 0.007 seconds (0.007276/sec)
C:\test>echo 127.0.0.1 | 874413.pl
1 lookups (0 found) in 0.007 seconds (0.007116/sec)
C:\test>echo 2.103.2.204 | 874413.pl
1 lookups (0 found) in 0.008 seconds (0.008237/sec)
Once the cache is hot--as would be the case if doing a large number of lookups--that speeds up considerably to well under 1 millisecond per: >perl -MList::Util=shuffle
-nE"chomp(@i=shuffle<>); say +(split':')[0] for @i[0..1e3];last" ips.t
+xt
|874413.pl >nul
1001 lookups (1001 found) in 0.456 seconds (0.000455/sec)
My crude test code: #! perl -slw
use strict;
use Time::HiRes qw[ time ];
open IPS, '<raw', 'ips.bin' or die $!;
my $size = -s( *IPS );
$size /= 6;
sub find {
local $/ = \6;
my $toFind = unpack 'N', pack 'C4', split '\.', shift;
my( $lo, $hi ) = ( 0, $size );
my( $ip, $u );
while( $lo <= $hi ) {
my $pos = ( $lo + $hi ) >> 1;
seek IPS, $pos*6, 0;
( $ip, $u ) = unpack 'Nn', <IPS>;
$hi = $pos - 1, next if $ip > $toFind;
$lo = $pos + 1, next if $ip < $toFind;
return join('.',unpack'C4',pack'N',$ip), $u if $ip == $toFind;
}
return;
}
my $start = time;
my $found = 0;
while( <> ) {
chomp;
my( $ip, $user ) = find( $_ );
#warn "$_ unassigned\n" and
next unless $user;
++$found;
printf "%s allocated to user;%u\n", $ip, $user;
}
my $taken = time() - $start;
warn sprintf "%d lookups ($found found) in %.3f seconds (%.6f/sec)\n",
+
$., $taken, $taken / $.;
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.
|