Есть огромный access.log 56 млн. строк.
Есть справочник адресов сетей областей 274 строки всего 28 областей
Задача "разрезать" access.log так, чтобы сформировать файл для каждой из 28 областей.
Мой алгоритм, брать по очереди каждую строку из access.log извлекать оттуда адрес накладывать на него маску (взятую из файла областей) и сравнивать по очереди с каждой строкой справочника.
Проблема в том что скорость обработки одной строки около 2-3 секунд, что для файла лога такого объема абсолютно не годится.
Делаю таким скриптом:
#!/bin/shIPLIST=allip.sorted
MAP="structure.name.net.mask"
export IFS="
"for IPSTRING in `cat $IPLIST`
do
for MAPSTRING in `cat $MAP`
do
MAPNETWORK=`echo $MAPSTRING|awk '{print $2}'`
MASK=`echo $MAPSTRING|awk '{print $3}'`
IPNETWORK=`ipcalc -n \`echo ${IPSTRING}"/"${MASK}\`|sed s/NETWORK=//g`if [ ${MAPNETWORK} = ${IPNETWORK} ]
then
MAPREGION=`echo $MAPSTRING|awk '{print $1}'`
echo $MAPREGION" "$MAPNETWORK" "$IPNETWORK" "$IPSTRING
break
fi
done
done
Если можете, подскажите, пожалуйста, как можно оптимизировать мою задачу?
а Perl религия не позволяет ?
>а Perl религия не позволяет ?эххх... если бы умел.
а если адресов в справочнике 10000 при 56 000 000 строк - 56х10^10 сравнений
неверный подход - перебор очень медленно
я например это делал двоичным делевом
Какие бинарные деревья? Не мечите бисер перед свиньями. Аффтар ниасилил даже вынесение подготовительных работ за пределы цикла и каждую итерацию заново парсит файл. Мало того, вместо одного вызова awk на весь $MAP файл он его вызывает дважды на каждую строку. Скрипт замечательный пример того как не надо программировать.
>Скрипт замечательный пример того как
>не надо программировать.можно подробнее описать что неправильно, ато я че-то непонел что я нетак сделал?
Дык вроде же указал, ладно попробую с большим количеством слов.
1. Все неизменные действия нужно выносить из цикла, особенно это касается вызова внешних программ и чтения файлов. У вас же на каждую строку в IPLIST заново обрабатывается MAP, причем эта обработка не зависит от значения текущей строки из IPLIST. Обработайте MAP один раз и храните все данные в памяти.
2. Сам MAP тоже обрабатывается на редкость криво. Зачем на каждую его строку дважды вызывать awk, когда можно обойтись одним вызовом awk на весь файл? Пример
for MAPSTRING in `cat $MAP`
do
MAPNETWORK=`echo $MAPSTRING|awk '{print $2}'`
MASK=`echo $MAPSTRING|awk '{print $3}'`
заменяем
awk '{print $2, $3}' $MAP | while read MAPNETWORK MASK; do
В данном случае конечно можно и вообще без awk обойтись, но это техника для общего случая.Ну а теперь подсчитайте сколько у вас _лишних_ вызовов внешних программ получилось и не удивляйтесь почему так медленно работает.
Я мог бы написать вам вариант на perl, но вы конечно забыли предоставить формат входных и выходных данных, телепатией не владею, так что ССЗБ