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.
RIP an inspiration; A true Folk's Guy

In reply to Re: Quickly determine which IP range an IP belongs to. by BrowserUk
in thread Quickly determine which IP range an IP belongs to. by punch_card_don

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.