Commit 6015ddaa by William Tisäter

Optimize _get_record

Before:

    _get_record() for 131072 addresses 0:00:19.744702
    _get_record() for 131072 addresses 0:00:19.088162
    _get_record() for 131072 addresses 0:00:19.362637
    _get_record() for 131072 addresses 0:00:19.874917

After:

    _get_record() for 131072 addresses 0:00:18.143153
    _get_record() for 131072 addresses 0:00:18.247334
    _get_record() for 131072 addresses 0:00:18.326092
    _get_record() for 131072 addresses 0:00:17.750563
parent 579a9a78
...@@ -22,9 +22,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>. ...@@ -22,9 +22,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/lgpl.txt>.
""" """
import os import os
import math
import socket import socket
import codecs import codecs
from math import floor
from threading import Lock from threading import Lock
try: try:
...@@ -34,6 +34,7 @@ except ImportError: ...@@ -34,6 +34,7 @@ except ImportError:
try: try:
from StringIO import StringIO from StringIO import StringIO
range = xrange # Use xrange for Python 2
except ImportError: except ImportError:
from io import StringIO, BytesIO from io import StringIO, BytesIO
...@@ -272,7 +273,7 @@ class GeoIP(object): ...@@ -272,7 +273,7 @@ class GeoIP(object):
@rtype: str @rtype: str
""" """
seek_org = self._seek_country(ipnum) seek_org = self._seek_country(ipnum)
if seek_org == self._databaseSegments: if not seek_org:
return None return None
read_length = (2 * self._recordLength - 1) * self._databaseSegments read_length = (2 * self._recordLength - 1) * self._databaseSegments
...@@ -344,7 +345,7 @@ class GeoIP(object): ...@@ -344,7 +345,7 @@ class GeoIP(object):
@rtype: dict @rtype: dict
""" """
seek_country = self._seek_country(ipnum) seek_country = self._seek_country(ipnum)
if seek_country == self._databaseSegments: if not seek_country:
return {} return {}
read_length = (2 * self._recordLength - 1) * self._databaseSegments read_length = (2 * self._recordLength - 1) * self._databaseSegments
...@@ -359,63 +360,49 @@ class GeoIP(object): ...@@ -359,63 +360,49 @@ class GeoIP(object):
record = { record = {
'dma_code': 0, 'dma_code': 0,
'area_code': 0, 'area_code': 0,
'metro_code': '', 'metro_code': None,
'postal_code': '' 'postal_code': None
} }
latitude = 0 latitude = 0
longitude = 0 longitude = 0
buf_pos = 0
# Get country char = ord(buf[0])
char = ord(buf[buf_pos])
record['country_code'] = const.COUNTRY_CODES[char] record['country_code'] = const.COUNTRY_CODES[char]
record['country_code3'] = const.COUNTRY_CODES3[char] record['country_code3'] = const.COUNTRY_CODES3[char]
record['country_name'] = const.COUNTRY_NAMES[char] record['country_name'] = const.COUNTRY_NAMES[char]
record['continent'] = const.CONTINENT_NAMES[char] record['continent'] = const.CONTINENT_NAMES[char]
buf_pos += 1 def read_data(buf, pos):
cur = pos
while buf[cur] != '\0':
cur += 1
return cur, buf[pos:cur] if cur > pos else None
def get_data(buf, buf_pos): offset, record['region_code'] = read_data(buf, 1)
offset = buf_pos offset, record['city'] = read_data(buf, offset + 1)
char = ord(buf[offset]) offset, record['postal_code'] = read_data(buf, offset + 1)
while char != 0: offset = offset + 1
offset += 1
char = ord(buf[offset])
if offset > buf_pos:
return offset, buf[buf_pos:offset]
return offset, ''
offset, record['region_code'] = get_data(buf, buf_pos)
offset, record['city'] = get_data(buf, offset + 1)
offset, record['postal_code'] = get_data(buf, offset + 1)
buf_pos = offset + 1
for j in range(3): for j in range(3):
char = ord(buf[buf_pos]) latitude += (ord(buf[offset + j]) << (j * 8))
buf_pos += 1
latitude += (char << (j * 8))
for j in range(3): for j in range(3):
char = ord(buf[buf_pos]) longitude += (ord(buf[offset + j + 3]) << (j * 8))
buf_pos += 1
longitude += (char << (j * 8))
record['latitude'] = (latitude / 10000.0) - 180.0 record['latitude'] = (latitude / 10000.0) - 180.0
record['longitude'] = (longitude / 10000.0) - 180.0 record['longitude'] = (longitude / 10000.0) - 180.0
if self._databaseType in (const.CITY_EDITION_REV1, const.CITY_EDITION_REV1_V6): if self._databaseType in (const.CITY_EDITION_REV1, const.CITY_EDITION_REV1_V6):
dmaarea_combo = 0
if record['country_code'] == 'US': if record['country_code'] == 'US':
dma_area = 0
for j in range(3): for j in range(3):
char = ord(buf[buf_pos]) dma_area += ord(buf[offset + j + 6]) << (j * 8)
dmaarea_combo += (char << (j * 8))
buf_pos += 1
record['dma_code'] = int(math.floor(dmaarea_combo / 1000)) record['dma_code'] = int(floor(dma_area / 1000))
record['area_code'] = dmaarea_combo % 1000 record['area_code'] = dma_area % 1000
record['metro_code'] = const.DMA_MAP.get(record['dma_code'])
record['metro_code'] = const.DMA_MAP.get(record['dma_code'])
params = (record['country_code'], record['region_code']) params = (record['country_code'], record['region_code'])
record['time_zone'] = time_zone_by_country_and_region(*params) record['time_zone'] = time_zone_by_country_and_region(*params)
...@@ -649,4 +636,3 @@ class GeoIP(object): ...@@ -649,4 +636,3 @@ class GeoIP(object):
""" """
addr = self._gethostbyname(hostname) addr = self._gethostbyname(hostname)
return self.time_zone_by_addr(addr) return self.time_zone_by_addr(addr)
...@@ -22,12 +22,13 @@ class TestGeoIPCityFunctions(unittest.TestCase): ...@@ -22,12 +22,13 @@ class TestGeoIPCityFunctions(unittest.TestCase):
self.us_record_data = { self.us_record_data = {
'city': 'Mountain View', 'city': 'Mountain View',
'region_code': 'CA', 'region_code': 'CA',
'area_code': 650,
'longitude': -122.05740356445312, 'longitude': -122.05740356445312,
'country_code3': 'USA', 'country_code3': 'USA',
'latitude': 37.419200897216797, 'latitude': 37.419200897216797,
'postal_code': '94043', 'postal_code': '94043',
'dma_code': 807, 'dma_code': 807,
'area_code': 650,
'metro_code': 'San Francisco, CA',
'country_code': 'US', 'country_code': 'US',
'country_name': 'United States', 'country_name': 'United States',
'continent': 'NA', 'continent': 'NA',
...@@ -37,12 +38,13 @@ class TestGeoIPCityFunctions(unittest.TestCase): ...@@ -37,12 +38,13 @@ class TestGeoIPCityFunctions(unittest.TestCase):
self.gb_record_data = { self.gb_record_data = {
'city': 'Tadworth', 'city': 'Tadworth',
'region_code': 'N7', 'region_code': 'N7',
'area_code': 0,
'longitude': -0.23339999999998895, 'longitude': -0.23339999999998895,
'country_code3': 'GBR', 'country_code3': 'GBR',
'latitude': 51.283299999999997, 'latitude': 51.283299999999997,
'postal_code': '', 'postal_code': None,
'dma_code': 0, 'dma_code': 0,
'area_code': 0,
'metro_code': None,
'country_code': 'GB', 'country_code': 'GB',
'country_name': 'United Kingdom', 'country_name': 'United Kingdom',
'continent': 'EU', 'continent': 'EU',
...@@ -107,7 +109,7 @@ class TestGeoIPCityFunctions(unittest.TestCase): ...@@ -107,7 +109,7 @@ class TestGeoIPCityFunctions(unittest.TestCase):
def testRecordByAddr(self): def testRecordByAddr(self):
equal_keys = ('city', 'region_name', 'area_code', 'country_code3', equal_keys = ('city', 'region_name', 'area_code', 'country_code3',
'postal_code', 'dma_code', 'country_code', 'postal_code', 'dma_code', 'country_code', 'metro_code',
'country_name', 'time_zone') 'country_name', 'time_zone')
almost_equal_keys = ('longitude', 'latitude') almost_equal_keys = ('longitude', 'latitude')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment