Когда дело доходит до этого, мне просто нужно знать, присутствует ли IP в любом из диапазонов 5M.
Я бы рассмотрел n-ary дерево, где n = 256, и работает от точечного адреса, а не от преобразованного целого числа.
Верхним уровнем будет массив из 256 объектов.Запись null
означает «Нет», нет диапазона, содержащего адрес, поэтому в вашем примере 192.168.1.0/24
array [192] будет содержать объект, но array [100] может быть нулевым, поскольку для любых 100 не определено ни одного диапазона..xxx / n
Хранимый объект содержит (ссылку на) другой массив [256] и спецификатор диапазона, будет задан только один из двух, поэтому 192.0.0.0/8
будет иметь спецификатор диапазона, указывающийвсе адреса в этом диапазоне должны быть отфильтрованы.Это учитывает такие вещи, как 192.255.0.0/10
, где первые 10 битов адреса значимы 1100 0000 11xx xxxx
- в противном случае вам необходимо проверить следующий октет в массиве 2-го уровня.
Первоначально объединять диапазоны перекрытия, еслилюбой, в более широкие диапазоны ... например, 3 .. 10
и 7 .. 16
становится 3 .. 16
... позволяет это, так как вам не нужно ассоциировать данный IP с , диапазон которого определил его.
Для этого требуется не более 8 сравнений.Каждый октет первоначально используется непосредственно в качестве индекса, за которым следует сравнение для нулевого значения, сравнение для терминального узла (это диапазон или указатель на следующий уровень дерева)
Теоретически потребление памяти в худшем случае равно 4GB (256 ^ 4)
, если каждый IP-адрес находился в диапазоне фильтрации, но, конечно, это объединилось бы в один диапазон, так что фактически это был бы только один объект диапазона.Более реалистичный наихудший случай, вероятно, будет больше похож на (256 ^ 3)
или 16,7 МБ.В реальном мире, вероятно, большинство узлов массива [256] на каждом уровне будут пустыми.
По сути, это похоже на кодирование Хаффмана / префиксов.Кратчайший префикс может заканчиваться, как только будет найден ответ (диапазон), поэтому часто вы будете иметь среднее значение < 4
сравнений.