aboutsummaryrefslogtreecommitdiffstats
path: root/main/gdnsd/geoip-speedup.patch
blob: 3816df44ed2b6a65a2e052ebf3ac698d15f0b9e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
From: Timo TerÃs <timo.teras@iki.fi>

plugin_geoip: speed up cities database loading

Gives over 10x speed-up in loading the large cities database.
http://code.google.com/p/gdnsd/issues/detail?id=18

diff --git a/plugins/meta/libgdmaps/gdmaps.c b/plugins/meta/libgdmaps/gdmaps.c
index 9d20351..6bbc410 100644
--- a/plugins/meta/libgdmaps/gdmaps.c
+++ b/plugins/meta/libgdmaps/gdmaps.c
@@ -1215,6 +1215,12 @@ typedef struct {
 } gdmap_t;
 
 typedef struct {
+    unsigned offset;
+    unsigned dclist;
+} offset_cache_item_t;
+#define OFFSET_CACHE_SIZE (1 << 18)
+
+typedef struct {
     char* pathname;
     uint8_t* data;
     const fips_t* fips;
@@ -1223,6 +1229,8 @@ typedef struct {
     int type;
     unsigned base;
     bool ipv6;
+
+    offset_cache_item_t *offset_cache[OFFSET_CACHE_SIZE];
 } geoip_db_t;
 
 F_NONNULL
@@ -1230,7 +1238,7 @@ static int geoip_db_close(geoip_db_t* db);
 F_NONNULLX(1)
 static geoip_db_t* geoip_db_open(const char* pathname, const fips_t* fips, const char* map_name, const bool city_required);
 F_NONNULLX(1, 2, 3)
-static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, const geoip_db_t* db, const geoip_db_t* db_v4o);
+static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, geoip_db_t* db, geoip_db_t* db_v4o);
 
 F_NONNULL
 static ntree_t* gdmap_make_tree(const gdmap_t* gdmap, const dclists_t* old_dclists) {
@@ -1957,10 +1965,18 @@ static unsigned city_lookup_dclist(const geoip_db_t* db, unsigned int offs, cons
 }
 
 F_NONNULL
-static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, const geoip_db_t* db, const unsigned int offset) {
+static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, geoip_db_t* db, const unsigned int offset) {
     dmn_assert(gdmap); dmn_assert(db);
 
     unsigned dclist = 0;
+    unsigned bucket_size = 0;
+    unsigned ndx = offset % OFFSET_CACHE_SIZE;
+
+    if (db->offset_cache[ndx]) {
+        for (bucket_size = 0; db->offset_cache[ndx][bucket_size].offset; bucket_size++)
+            if (db->offset_cache[ndx][bucket_size].offset == offset)
+                return db->offset_cache[ndx][bucket_size].dclist;
+    }
 
     switch(db->type) {
         case GEOIP_CITY_EDITION_REV1_V6:
@@ -1983,6 +1999,11 @@ static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, const geoi
             break;
     }
 
+    db->offset_cache[ndx] = realloc(db->offset_cache[ndx], sizeof(offset_cache_item_t) * (bucket_size+2));
+    db->offset_cache[ndx][bucket_size].offset = offset;
+    db->offset_cache[ndx][bucket_size].dclist = dclist;
+    db->offset_cache[ndx][bucket_size+1].offset = 0;
+
     return dclist;
 }
 
@@ -1991,7 +2012,7 @@ static unsigned get_dclist(const gdmap_t* gdmap, const ntree_t* tree, const geoi
 // C really needs a better macro/template idea :(
 #define DEFUN_TREE_XLATE(IPVN, IPTYPE, IPZERO, BITDEPTH, V4ROOT_CODE, SKIP_CODE) \
 F_NONNULL              \
-static int geoip_tree_xlate_ ## IPVN(const gdmap_t* gdmap, ntree_t* tree, const geoip_db_t* db) { \
+static int geoip_tree_xlate_ ## IPVN(const gdmap_t* gdmap, ntree_t* tree, geoip_db_t* db) { \
     dmn_assert(gdmap); dmn_assert(tree); dmn_assert(db); \
     struct {                                             \
         int depth;                                       \
@@ -2107,7 +2128,7 @@ DEFUN_TREE_XLATE(v4, uint32_t, 0, 32, ;, ;)
 
 DEFUN_TREE_XLATE(v6, struct in6_addr, ip6_zero, 128, V6_V4ROOT_CODE, V6_SKIP_CODE)
 
-static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, const geoip_db_t* db, const geoip_db_t* db_v4o) {
+static int geoip_tree_xlate(const gdmap_t* gdmap, ntree_t* tree, geoip_db_t* db, geoip_db_t* db_v4o) {
     dmn_assert(gdmap); dmn_assert(tree); dmn_assert(db);
 
     log_info("plugin_geoip: map '%s': Processing GeoIP database '%s'...", gdmap->name, gdmap->geoip_path);
@@ -2145,6 +2166,8 @@ static int geoip_db_close(geoip_db_t* db) {
         }
     }
 
+    for (unsigned i = 0; i < OFFSET_CACHE_SIZE; i++)
+        free(db->offset_cache[i]);
     if(db->pathname)
         free(db->pathname);
     free(db);