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.