URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 84034
[ Назад ]

Исходное сообщение
"нужен совет"

Отправлено mesmeridze , 08-Фев-09 23:02 
Есть огромный access.log 56 млн. строк.
Есть справочник адресов сетей областей 274 строки всего 28 областей
Задача "разрезать" access.log так, чтобы сформировать файл для каждой из 28 областей.
Мой алгоритм, брать по очереди каждую строку из access.log извлекать оттуда адрес накладывать на него маску (взятую из файла областей) и сравнивать по очереди с каждой строкой справочника.
Проблема в том что скорость обработки одной строки около 2-3 секунд, что для файла лога такого объема абсолютно не годится.
Делаю таким скриптом:
#!/bin/sh

IPLIST=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
Если можете, подскажите, пожалуйста, как можно оптимизировать мою задачу?


Содержание

Сообщения в этом обсуждении
"нужен совет"
Отправлено v.i.t , 09-Фев-09 00:00 
а Perl религия не позволяет ?  

"нужен совет"
Отправлено mesmeridze , 09-Фев-09 10:57 
>а Perl религия не позволяет ?

эххх... если бы умел.


"нужен совет"
Отправлено Pahanivo , 09-Фев-09 07:54 
а если адресов в справочнике 10000 при 56 000 000 строк - 56х10^10 сравнений
неверный подход - перебор очень медленно
я например это делал двоичным делевом

"нужен совет"
Отправлено angra , 09-Фев-09 09:12 
Какие бинарные деревья? Не мечите бисер перед свиньями. Аффтар ниасилил даже вынесение подготовительных работ за пределы цикла и каждую итерацию заново парсит файл. Мало того, вместо одного вызова awk на весь $MAP файл он его вызывает дважды на каждую строку. Скрипт замечательный пример того как не надо программировать.


"нужен совет"
Отправлено mesmeridze , 09-Фев-09 10:55 
>Скрипт замечательный пример того как
>не надо программировать.

можно подробнее описать что неправильно, ато я че-то непонел что я нетак сделал?


"нужен совет"
Отправлено angra , 09-Фев-09 11:59 
Дык вроде же указал, ладно попробую с большим количеством слов.
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, но вы конечно забыли предоставить формат входных и выходных данных, телепатией не владею, так что ССЗБ