Super fast IP to lat/lng in Rails – Part 2

In Super fast IP to lat/lng in Rails, I showed a solution for fast IP to lat/lng resolution in rails. I called it “Super fast” because it performed orders of magnitude faster the the RESTful interface, but it was also “Super fast” to implement. That being said, Kyle made a comment to check out the GeoIP gem. I had heard of MaxMind before, but I didnt want to spend hundreds of dollars to solve this problem. What I didnt know was they also have a free download of their “lite” datasource. They have a GeoLiteCountry and GeoLiteCity version, although only the City version has lat/lng info. They provide wrappers in most languages (including Ruby), and while Kyle’s suggested geoip, I found geoip_city on RubyForge which I like a bit better.



[UPDATED]: I had forgotten to include the install instructions for getting the GeoIP C library.

Install the C bindings, the gem (which isnt packaged as a gem for easy download) and get the data.

wget http://www.maxmind.com/download/geoip/api/c/GeoIP.tar.gz
tar -zxvf GeoIP.tar.gz
cd GeoIP
./configure && make && sudo make install

wget http://rubyforge.org/frs/download.php/27077/geoip_city-0.1.gem
sudo gem install geoip_city-0.1.gem
wget http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
sudo mkdir /usr/local/share/GeoIP
sudo mv GeoLiteCity.dat /usr/local/share/GeoIP/GeoLiteCity.dat

Then the ruby part:

>> require 'geoip_city'
>> g = GeoIPCity::Database.new('/usr/local/share/GeoIP/GeoLiteCity.dat')
>> res = g.look_up('4.2.2.2')
>> puts "lat: #{res[:latitude]} lng: #{res[:longitude]}"
lat: 38.0 lng: -97.0

So the question is (although its probably obvious), which is faster?

>>  Benchmark.measure { 1000.times {Hostip.geocode('4.2.2.2')}}.total
=> 1.02
>>   Benchmark.measure { 100000.times {g.look_up('4.2.2.2')}}.total
=> 0.5

Conclusion? The C library is MUCH faster than my database version. 200k req/s vs. 1k req/s. As a side note, I also tested the “geoip” gem, and it was about 3x faster than my database version.


But all in all, for the 5 minutes it took me to write the original version, it was fast enough… but MaxMind GeoLiteCity + the geoip_city gem is Super fast-er.

9 Comments

  1. Brian says:

    I tried to download and install the gem and got this:
    Building native extensions. This could take a while…
    ERROR: While executing gem … (RuntimeError)
    Error instaling geoip_city-0.1.gem:
    ERROR: Failed to build gem native extension.

    ruby extconf.rb install geoip_city-0.1.gem
    checking for GeoIP_record_by_ipnum() in -lGeoIP… no
    *** extconf.rb failed ***
    Could not create Makefile due to some reason, probably lack of
    necessary libraries and/or headers. Check the mkmf.log file for more
    details. You may need configuration options.

    Provided configuration options:
    –with-opt-dir
    –without-opt-dir
    –with-opt-include
    –without-opt-include=${opt-dir}/include
    –with-opt-lib
    –without-opt-lib=${opt-dir}/lib
    –with-make-prog
    –without-make-prog
    –srcdir=.
    –curdir
    –ruby=/usr/local/bin/ruby
    –with-geoip-dir
    –without-geoip-dir
    –with-geoip-include
    –without-geoip-include=${geoip-dir}/include
    –with-geoip-lib
    –without-geoip-lib=${geoip-dir}/lib
    –with-GeoIPlib
    –without-GeoIPlib

    Gem files will remain installed in /usr/local/lib/ruby/gems/1.8/gems/geoip_city-0.1 for inspection.
    Results logged to /usr/local/lib/ruby/gems/1.8/gems/geoip_city-0.1/gem_make.out

  2. Brian,

    Good catch. I already had the GeoIP C library installed. I’ve since updated the install instructions above to include that.

    Thanks.
    Aaron

  3. Muntasim says:

    Hi, I am in trouble to install GeoIP C library in windows…
    Please help..

    Thanks in advance

  4. Aman Gupta says:

    Does GeoIPCity return any city information?

    irb(main):008:0> g.look_up(’99.136.101.165′)
    => {:country_name=>"United States", :latitude=>38.0, :longitude=>-97.0, :country_code=>"US", :country_code3=>"USA"}

  5. That’s great, you saved me a lot of time, and you even did the benchmarks!

  6. Abdul Barek says:

    Hi all, I wanna use geo_ip for windows.Please let me know if anybody kind on me.I did it for linux server but can not use for windows(XP).Please help me ASAP

    Thanks

  7. Tom Y says:

    Hi, I installed this plugin step by step, and when I run require ‘geoip_city’, I got following error msg:

    LoadError: libGeoIP.so.1: cannot open shared object file: No such file or directory – /var/lib/gems/1.8/gems/geoip_city-0.1/./geoip_city.so

    Can anyone help me with this? Thanks in advance!

  8. Amjith PS says:

    Hi,

    Can you fix this error,

    I have error in

    –>require ‘geoip_city’

    Its missing this file., with error "no such file to load — geoip_city"

    Can anyone tel me where this file is located?

    Thanks in advance.

    Amjith PS

  9. JD says:

    Good find on the geoip_city gem aaron, it really is ridiculously faster (and getting a Hash back is a lot nicer also). From their README the default is to load the whole binary db into RAM, which will use at least 27MB of it (I haven’t tested how much it actually uses). But even passing the :filesystem parameter it seems a good 20x faster than the regular geoip gem.