Вы читаете журнал [info]nponeccop

Дважды мудак - RWA Contest [entries|archive|friends|userinfo]
Декларативное рулит

Site Meter

[ website | Мой сайт ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

RWA Contest [Окт. 26, 2011|15:47 pm]
Previous Entry В избранное Поделиться Next Entry
[Tags|, ]

Тут по моему старому проекту возникла задачка: сделать фильтрацию по диапазонам IP-адресов. Буду делать quick and dirty-реализацию на си с классами, если кто возжелает, может реализовать на своём любимом языке а потом сравним.

Задача такова: есть ASCIIZ-строка с IP-адресом, надо вернуть true, если этот адрес попадает в один из диапазонов, перечисленных в файле.

Файл текстовый такого формата,

192.168.1.3,192.168.1.5
192.168.2.4,193.0.0.3

Файл не отсортирован, дипапазоны произвольные и могут пересекаться. Первый адрес меньше второго или равен ему. Пересечение диапазонов можно обрабатывать двумя путями: лиюо отказываться грузить такой файл и выдавать что с чем пересеклось, либо не отказываться и корректно работать в таких условиях.

Файл грузится один раз и потом десятки миллионов раз лукапится. Записей в конфиге - сотни.

UPD: я не спрашивал, как мне это имплементить - задача школьная. Я просил добровольцев из числа читателей заимплементить это на ФЯ и померить.
СсылкаОтветить

Comments:
[User Picture]From: [info]deni_ok
2011-10-26 12:58 pm none (UTC)

(Link)

Хорошая, студентам подкину.
From: (Anonymous)
2011-10-26 01:02 pm none (UTC)

(Link)

Эх, реализовано такое уже в libgeoip, простой битовый trie.
[User Picture]From: [info]volodymir_k
2011-10-26 01:30 pm none (UTC)

(Link)

А какие ограничения? Тупо сделать 512Мб массив битовых флагов, заполнить битом 1 диапазоны, и быстрее уже ничего не может быть. Разве что за счёт локальности памяти и кэша процессора -- на каком мерять собираются?
[User Picture]From: [info]nponeccop
2011-10-26 04:04 pm none (UTC)

(Link)

Не, 512 мбайт у нас нету. 1 ядро Xeon Core2, детальнее пока не скажу.
[User Picture]From: [info]antilamer
2011-10-26 01:54 pm none (UTC)

(Link)

Binary search по списку границ, после устранения дублей и пересечений любым способом, думаю, будет быстрее всего, раз сотни.
From: [info]smalgin
2011-10-26 02:31 pm none (UTC)

(Link)

ну или hashtables тоже можно.
[User Picture]From: [info]ximaera
2011-10-26 03:23 pm none (UTC)

(Link)

Т. е. IP-адреса указываются не целыми префиксами, а такими вот диапазонами? Если не секрет, в чём смысл такой задачи?
[User Picture]From: [info]nponeccop
2011-10-26 03:50 pm none (UTC)

(Link)

смысла много разного.

1) для вычисления CIDR нужна отдельная тулза, а минимальный и максимальный IP можно определить по набору IP в логе визуально

2) пользователи не знают, что такое CIDR

3) фильтрация по CIDR не имеет физического смысла
[User Picture]From: [info]grez_ua
2011-10-26 04:03 pm none (UTC)

(Link)

У нас нечто подобное забыдлокоджено "в лоб".
Масив пар лонгов "старт, енд".
А потом приводим искомый адрес тоже в лонг, и тупым перебором и сравнением по этому масиву. Для пар сотен запесей работает заебца, как по мне.
[User Picture]From: [info]nponeccop
2011-10-26 04:16 pm none (UTC)

(Link)

Ну, у нас есть нехорошая тенденция разрастания всех конфигов до гигабайта, поэтому линейный поиск - это уж совсем ахтунг.

Один из текущих IP-фильтров разросся до 128к индивидуальных айпишников, с этим тоже такое может произойти, т.е. стараемся писать масштабируемо, если это не требует значительных работ. Случай с линейным vs бинарным поиском - как раз то.
From: (Anonymous)
2011-10-26 05:34 pm none (UTC)

(Link)

Обычно для range lookup используются multiway range trees и segment trees. Для пересекающихся диапазонов можно сначала сделать "нормализацию".
[User Picture]From: [info]nponeccop
2011-10-26 07:26 pm none (UTC)

(Link)

у нас не "обычно":

1) нет обновлений
2) нет префиксов
3) нет задачи искать самый длинный префикс

В топку.
[User Picture]From: [info]os80
2011-10-26 06:59 pm none (UTC)

(Link)

Я не понял, как потом сравнивать будем.
[User Picture]From: [info]nponeccop
2011-10-26 07:40 pm none (UTC)

(Link)

Псевдокод:
sub find(ip_str)
{
   ip_uint32 = ip2int(ip_str)
   forall (entry in config)
   {
      if ip_uint32 >= entry.start && ip.uint32 <= entry.end
         return true
   }
   return false
}
Идея должна быть понятна. Алгоритм, разумеется, должен быть быстрее линейного.
[User Picture]From: [info]Odobenus Rosmarus (rosmarus) [blogspot.com]
2011-10-27 12:20 am none (UTC)

Нате вам

(Link)

Навскидку, то что за полчаса написалось на эрланге.

http://ubuntuone.com/4jM6BSoxbUrRhipSCBGLni

А что мерить то?
[User Picture]From: [info]Odobenus Rosmarus (rosmarus) [blogspot.com]
2011-10-27 02:32 am none (UTC)

(Link)

Вариант номер 2 - дерево (первый вариант был через hashtable).
http://ubuntuone.com/4pHqBhfOJvUnoraop5uJYx (http://ubuntuone.com/4pHqBhfOJvUnoraop5uJYx)

Работает так:

F = iptree:read("RU_ipranges.txt").

Естественно со своим именем файла. Результат - функция для проверки.
Типа

3> F = iptree:read("RU_ipranges.txt").

4> F("192.168.1.1").
not_found
5> F("46.28.130.1").
found


[User Picture]From: [info]nponeccop
2011-10-27 11:24 am none (UTC)

(Link)

Надо срочно писать ответ на node.js :)
[User Picture]From: [info]pingback_bot
2011-10-27 02:55 am none (UTC)

No title

(Link)

User [info]grundik referenced to your post from No title saying: [...] http://nponeccop.livejournal.com/225261.html [...]
From: [info]nivanych
2011-10-27 10:39 am none (UTC)

(Link)

Не указана важная деталь — реакция программы на ошибки.
[User Picture]From: [info]nponeccop
2011-10-27 11:16 am none (UTC)

(Link)

Это специально сделано. Всё неспецифицированное можно делать как угодно.
[User Picture]From: [info]pingback_bot
2011-10-27 10:20 pm none (UTC)

Попробовал задачку <lj user=nponeccop>.

(Link)

User [info]thesz referenced to your post from Попробовал задачку [info]nponeccop. saying: [...] Задачка [...]
[User Picture]From: [info]pingback_bot
2011-10-28 04:53 pm none (UTC)

Пятничное трололо

(Link)

User [info]justy_tylor referenced to your post from Пятничное трололо saying: [...] Пример кода для http://nponeccop.livejournal.com/225261.html [...]
From: [info]love5an
2011-10-29 01:26 pm none (UTC)

(Link)

[User Picture]From: [info]pingback_bot
2011-10-29 02:04 pm none (UTC)

RWA Contest

(Link)

User [info]inv2004 referenced to your post from RWA Contest saying: [...] насочинял для этой [...]
From: (Anonymous)
2011-10-29 05:31 pm none (UTC)

(Link)

Выше thesz уже спрашивал - важно ли находить сам диапазон, в который попал IP? Иначе можно обойтись 3-мя изначально нулевыми матрицами a,b,c размера 256x256. Если есть адрес 100.101.102.103, то a[100,101]=1, b[101,102]=1, c[102,103]=1. И так для каждого IP из диапазонов в процессе прочтения файла (долго, что делать, но зато искать проще). Поиск как строить имхо очевидно и должно получиться достаточно быстро. Матрицы можно размотать в массивы стандартным образом, конечно.

//EO
[User Picture]From: [info]nponeccop
2011-10-29 05:32 pm none (UTC)

(Link)

Сам диапазон находить не нужно
[User Picture]From: [info]gliv
2011-10-31 03:10 pm none (UTC)

(Link)

А у количества данных какие порядки?
Сколько диапазонов?
Сколько IP- адресов?
[User Picture]From: [info]nponeccop
2011-10-31 04:51 pm none (UTC)

(Link)

IP-адресов - от тысяч до миллиарда. Причём из-за дурацкой архитектуры распараллеливания нельзя проверять адреса пачками (т.е. передавать в проверялку можно только по одному).

Диапазонов - единицы тысяч.
[User Picture]From: [info]pingback_bot
2011-10-31 07:27 pm none (UTC)

решение задачи про фильтрацию IP-адресов на хаскеле

(Link)

User [info]gliv referenced to your post from решение задачи про фильтрацию IP-адресов на хаскеле saying: [...] Разобрался с задачей [...]
[User Picture]From: [info]inv2004
2011-11-01 12:24 am none (UTC)

(Link)

Ищу всё за чуть больше секунды:

http://inv2004.livejournal.com/144272.html

Всё: 10^6 ip адресов на 7000 диапазонов.
[User Picture]From: [info]inv2004
2011-11-01 03:04 pm none (UTC)

(Link)

Чуть больше полусекунды.

Исходник тут: http://dl.dropbox.com/u/34917039/ip.k

m:0N,{1+|/x#iph}'1+!#ipl
f:{x<m@ipl _bin x}