D Paste by downs
Description: geobench.d, correct version
Hide line numbers

Create new paste
Post a reply
View replies

Paste:
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  
102  
103  
104  
105  
module geobench;
import tools.time, tools.log, tools.base, std.string, std.socket;

uint toNumeric(string ip) {
  uint res; ubyte cur;
  foreach (ch; ip) {
    if (ch == '.') { res = (res << 8) + cur; cur = 0; }
    else cur = cur * 10 + (ch - '0');
  }
  res = (res << 8) + cur;
  return res;
}

string ipToString(uint ip) {
  return ((cast(ubyte*) &ip)[0 .. 4].reverse /map/ (ubyte b) { return toString(b); }).join(".");
}

struct _IfFails(T) {
  T alternative;
  T opOr_r(lazy T left) {
    try return left();
    catch (Object obj) return alternative;
  }
}

_IfFails!(Unstatic!(T)) IfFails(T)(T alt) { _IfFails!(Unstatic!(T)) res; res.alternative = alt; return res; }

class GeoIP {
  import std.file;
  static {
    struct entry {
      uint start, end;
      string country;
    }
    entry[] list;
    string lookup(uint what) {
      auto range = list;
      while (range.length > 1) {
        auto center = range[$/2];
        if (center.start == what) return center.country;
        if (center.start < what) range = range[$/2 .. $];
        else range = range[0 .. $/2];
      }
      if (range[0].end <= what) throw new Exception(ipToString(what)~" not found in GeoIP list!");
      return range[0].country;
    }
  }
  static this() {
    string[string] countries; // lookup is by string equality
    "GeoIPCountryWhois.csv".read().castLike("").split("\n") /map/ (string line) {
      line = line.strip();
      if (!line.length) return;
      auto parts = line[1 .. $-1].split("\",\""); // remove ""s
      auto ip = parts[0], to_ip = parts[1];
      entry e;
      // why parse IPs? Let the system do it for us.
      e.start = ip.toNumeric();
      e.end = to_ip.toNumeric();
      e.country = parts[$-1];
      if (auto p = e.country in countries) e.country = *p;
      else countries[e.country] = e.country;
      list ~= e; // yes they're ordered
    };
    logln(list.length, " ranges added, using ", countries.values.length, " countries. ");
    logln("Performing lookup tests ... ");
    auto start = sec();
    long total, correct;
    foreach (line; "GeoIPCountryWhois.csv".read().castLike("").split("\n")) {
      line = line.strip();
      if (!line.length) continue;
      auto parts = line[1 .. $-1].split("\",\""); // remove ""s
      auto ip = parts[0];
      total ++;
      if (parts[5] == lookup(ip.toNumeric())) correct ++;
    }
    auto stop = sec();
    logln(correct, " / ", total, " validated in ", stop-start, "s");
    if (correct != total) throw new Exception("Please fix this first");
    logln("By the way: 10.0.0.1 -> ", lookup("10.0.0.1".toNumeric()) |IfFails("FAILURE"),
      " and 192.116.192.9 -> ", lookup("192.116.192.9".toNumeric()) |IfFails("FAILURE"));
  }
}

import tools.mersenne;
void main() {
  long count, failcount;
  auto last = sec();
  auto empty = IfFails("");
  while (true) {
    string country;
    for (int i = 0; i < 16; ++i) {
      auto rand_ip = rand();
      country = GeoIP.lookup(rand_ip) | empty;
      if (!country.length) failcount ++;
      count ++;
    }
    auto s = sec();
    if (s > last + 1) {
      last = s;
      logln(count, " lookups per second, ", failcount, " of them failed, last country was \"", country, "\"");
      count = 0; failcount = 0;
    }
  }
}

Replies:
Reply by GFwVIjXBDiqc
Please teach the rest of these internet hooliagns how to write and research!

    (some replies deleted)