Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Оптимизация времени выполнение маленького цикла


Автор: Step 2.1.2009, 01:47
Имеем вот такой циклик, который умудряется обрабатывать  порядка 2863311 пакетов в секунду
единственное, что меня не устраивает что данный код практически полностью загружают процессор
Код

do{
        rec = recvfrom(eth0_if, (__u8 *)buff, ifp.mtu + 18, 0, NULL, NULL);
        if(rec <= 0 || rec > ETH_FRAME_LEN+20) {
            perror("recvfrom\n");
            return -1;
        }
        eth=buff;
        if((eth->h_proto) == 0x0008){
            ip=buff + ETH_HLEN;
                __u8 net;
                if ((ip->daddr & 0x000000ff)==0x0000000a) {
                    net=(__u8)((ip->daddr & 0x00fe0000)>>16);
                    counter_net[net]+=rec;
                }
                counter_proto[ip->protocol]++;
                t=time(NULL);
                if (t>et)
                {
                    et=t;
                    counter_net[256]=0;
                    sendto(sc,(char *)counter_net,257*4,0,(struct sockaddr *) &RecvAddr,lens);
                    counter_proto[256]=1;
                    sendto(sc,(char *)counter_proto,257*4,0,(struct sockaddr *) &RecvAddr,lens);
                    counter_packet_size[256]=2;
                    counter_packet_size[(rec>>6)&0x00ff]++;
                    sendto(sc,(char *)counter_packet_size,257*4,0,(struct sockaddr *) &RecvAddr,lens);
                    int i=0;
                    for (i=0;i<256;i++){
                        counter_net[i]=0;
                        counter_proto[i]=0;
                        counter_packet_size[i]=0;
                    }
                }
        }

    }while(1);


принимаю любые идеи по оптимизации

Автор: vinick 2.1.2009, 12:11
По идее select может снизить нагрузку на процессор, но в этом случае я не уверен.

Код

       counter_packet_size[256]=2;
       counter_packet_size[(rec>>6)&0x00ff]++;
       sendto(sc,(char *)counter_packet_size,257*4,0,(struct sockaddr *) &RecvAddr,lens);
       int i=0;
       for (i=0;i<256;i++){
            counter_net[i]=0;
            counter_proto[i]=0;
            counter_packet_size[i]=0;
      }

сам цикл имеет смысл заменить на memset, и в массиве counter_packet_size - всегда используется только один элемент, обнулять его потом целиком нет смысла,да и вместо самого массива дешевле отправлять только одно значение (rec>>6)&0x00ff, но это потребует изменения принимающей стороны. Еще, может быть объединить все три массива в один и отправлять одним вызовом sendto.

Автор: MAKCim 2.1.2009, 12:53
Step, 
1. концептуальная оптимизация - использование отображения пакетов на кольцевой буфер через mmap
ну и мультиплексация через epoll
это позволит уменьшить количество вызовов recvfrom
подробнее в linux/Documentation/networking/packet_mmap.txt
2. фильтрация на уровне сниффера
достаточо при создании пакетного сокета указать третьим параметром htons(ETH_P_IP)

Добавлено @ 12:59
vinick,аз
memset - это тоже цикл, хоть и оптимизированный
что касается sendto, то он вызывается по таймауту, а таймаут отсчитывается по секундам (используется time(NULL)), поэтому sendto вызывается не чаще 1-го раза в секунду
а т. к за одну секунду приходит больше 2-х миллионов пакетов, то оптимизировать это не имеет никакого смысла

Автор: Step 2.1.2009, 18:09
MAKCim, спасибо,
вы бы не могли пояснить в двух словах
1. "позволит уменьшить количество вызовов" я не совсем понял, за счет чего, мне нужно обрабатывать каждый пакет, приведенная схема обработки это только начало
2. htons(ETH_P_IP) в двух словах что это чего я себя лишаю, и что преобретаю

Автор: MAKCim 2.1.2009, 18:37
Цитата(Step @  2.1.2009,  18:09 Найти цитируемый пост)
 "позволит уменьшить количество вызовов" я не совсем понял, за счет чего, мне нужно обрабатывать каждый пакет, приведенная схема обработки это только начало

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

Цитата(Step @  2.1.2009,  18:09 Найти цитируемый пост)
htons(ETH_P_IP) в двух словах что это чего я себя лишаю, и что преобретаю 

лишаешь себя возможности обработки не IP-пакетов
приобретаешь...
весь "мусор" типа ARP и ICMP отбрасывается

Автор: Step 2.1.2009, 19:39
Цитата(MAKCim @  2.1.2009,  18:37 Найти цитируемый пост)
в существующей схеме для получения одного пакета нужен один вызов recvfrom
при использовании отображения мы через epoll_wait получим уведомление о том, что пришел как минимум один пакет
его считывание - это не вызов recvfrom, а чтение части отображенного на адресное пространство процесса буфера
иными словами, используя один вызов epoll_wait, мы можем прочитать более одного пакета без перехода в режим ядра

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

Добавлено через 1 минуту и 15 секунд
Цитата(MAKCim @  2.1.2009,  18:37 Найти цитируемый пост)
лишаешь себя возможности обработки не IP-пакетов
приобретаешь...
весь "мусор" типа ARP и ICMP отбрасывается 

smile жестокое лишение, если арп мне действительно не нужен на данном этапе, то все остальное нужно просто позарез

Автор: MAKCim 2.1.2009, 19:48
Цитата(Step @  2.1.2009,  19:39 Найти цитируемый пост)
жестокое лишение, если арп мне действительно не нужен на данном этапе, то все остальное нужно просто позарез 

а, ну если нужно, тогда нужно
я просто по коду смотрел
там только на IP проверка

Цитата(Step @  2.1.2009,  19:39 Найти цитируемый пост)
т.е. если я правильно понял, мы в этом случае работаем напрямую с буфером приема сетевой карты, избавляем себя от целого ряда ненужных операций

напрямую с буфером мы не работаем
но от целого ряда ненужных операций себя избавляем  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)