How To Use GeoIP2 (mmdb) Database With Perl

Published on Author gryzli

This article is the result of my struggles to properly use GeoIP v2 database within Perl. 

 

TL;DR 

The FASTEST way to use the database is by installing and utilizing the “MaxMind::DB::Reader::XS” perl module. 

And here is a tiny example:

use MaxMind::DB::Reader::XS ; 
use Data::Dumper; 
my $geoip_country = MaxMind::DB::Reader::XS->new( file => '/usr/share/GeoIP/GeoIP2-Country.mmdb' );
print Dumper $geoip_country->record_for_address('1.1.1.1'); 

 

 

Possibilities for using GeoIP v2 DB 

You can choose from the following modules, which support GeoIP2: 

  • GeoIP2::Database::Reader
  • MaxMind::DB::Reader::XS
  • MaxMind::DB::Reader

 

Keep in mind that GeoIP2::Database::Reader is the worst performer, working almost 5x times slower than MaxMind::DB::Reader::XS for querying the country database.

 

This is a test perl script to test the performance of all the three modules, with some randomly generated ips: 

#!/usr/bin/perl  

use strict;  
use warnings;  
use GeoIP2::Database::Reader;  
use MaxMind::DB::Reader;  
use MaxMind::DB::Reader::XS;  
use Data::Dumper;  


sub get_ips {  
   # --------- 
   # Generate some number of ips 
   # ---------------- 
   my @ips;  
   foreach my $a (1 .. 255) {  
       foreach my $b ( 1 .. 255 ) { 
           foreach my $c ( 1 .. 5 ) { 
               push @ips, "1.$c.$a.$b";  
           } 
       }  
   }  
   return @ips;  
}  



my @ips = get_ips();  


if (grep {/use_maxmind_reader_xs/} @ARGV){ 
   print "Doing geoip lookup for " . scalar(@ips) . " number of ips, with MaxMind::DB::Reader::XS module ...\n"; 
   my $reader_country = MaxMind::DB::Reader::XS->new( file => '/usr/share/GeoIP/GeoIP2-Country.mmdb' ); 
   foreach (@ips){ 
       my $data = $reader_country->record_for_address($_);  
   }  
}  

elsif (grep {/use_maxmind_reader$/} @ARGV){ 
   print "Doing geoip lookup for " . scalar(@ips) . " number of ips, with MaxMind::DB::Reader module ...\n"; 
   my $reader_country = MaxMind::DB::Reader->new( file => '/usr/share/GeoIP/GeoIP2-Country.mmdb' ); 
   foreach (@ips){ 
       my $data = $reader_country->record_for_address($_);  
   }  
}  

elsif ( grep {/use_geoip2_reader/} @ARGV ){  
   print "Doing geoip lookup for " . scalar(@ips) . " number of ips, with GeoIP2::Database::Reader module ...\n"; 
   my $reader_country = GeoIP2::Database::Reader->new( file => '/usr/share/GeoIP/GeoIP2-Country.mmdb');  
   foreach (@ips){ 
       my $data = $reader_country->country( ip => $_);  
   }  

}  
else{  
   die("Invalid option provided. Try with: --use_maxmind_reader_xs or --use_maxmind_reader or --use_geoip2_reader ");  
} 

 

And some usage examples: 

 
/root/scripts# time perl geoip_lookup.pl --use_maxmind_reader_xs
Doing geoip lookup for 325125 number of ips, with MaxMind::DB::Reader::XS module ...

real 0m4.301s
user 0m4.248s
sys 0m0.053s

#----------------------

/root/scripts# time perl geoip_lookup.pl --use_geoip2_reader
Doing geoip lookup for 325125 number of ips, with GeoIP2::Database::Reader module ...

real 0m21.326s
user 0m21.248s
sys 0m0.072s

 

 

Happy GeoIP v2 querying.