Многопоточность не влияет на производительность

#c #multithreading #performance #parallel-processing #packet-sniffers

#c #многопоточность #Производительность #параллельная обработка #анализаторы пакетов

Вопрос:

Я работаю над своим анализатором пакетов. существует функция workerConnection (), которая выполняет основные процессы с пакетами следующим образом. Он считывает пакет из _Connection_buffer, который определен как std::string* _Connection_buffer= new std::string[_Max_Element_Connection_buffer] , затем разбивает пакеты на пробелы и выполняет с ними некоторые действия. все работает хорошо, за исключением выполнения параллельной обработки workerConnection ().

Как видно из workerConnection(), в первом цикле каждый поток принимает уникальный номер в качестве своего собственного ‘MyID’. затем использует свой MyID в качестве смещения для чтения пакетов из _Connection_buffer .

Я уверен, что при параллельной обработке workerConnection () каждый поток обрабатывает не все пакеты, а только пакеты (_Max_Element_Connection_buffer /_ConnectionThreadCount).

 void
workerConnection() {
    short MyID = 0;
    _Connection_tn->_mtx.lock();

    for (int n = 0; n < _ConnectionThreadCount; n  ) {
        if (_Connection_tn->getMyNumber[n] != 100) {
            MyID = _Connection_tn->getMyNumber[n];
            _Connection_tn->getMyNumber[n] = 100;
            break;
        }
    }
    _Connection_tn->_mtx.unlock();
    LOG_INFO("Session Worker :%d started", MyID);
    long int index = 0;
    s_EntryItem* entryItem = NULL; 
    uint32_t srcIP_num;
    uint64_t p_counter=0;

    std::string connectionPayload1 = "";         connectionPayload1.reserve(40);
    std::string connectionPayload2 = "";         connectionPayload2.reserve(40);
    std::string connectionPayload = "";         connectionPayload.reserve(150);

    std::string part;         part.reserve(30);
    std::string srcIP_str;    srcIP_str.reserve(15);
    std::string t;            t.reserve(50);
    std::string line;         line.reserve(_snapLengthConnection   1);
    std::string Protocol;     Protocol.reserve(3);
    std::string srcIP_port;   Protocol.reserve(7);

    std::vector<std::string> _CStorage(_storage_Count_Connection);
    struct timeval start, end;
    long mtime, secs, usecs;        
    gettimeofday(amp;start, NULL);
    for (index = MyID; index < _Max_Element_Connection_buffer; index =_ConnectionThreadCount) {                        
        if (unlikely(p_counter   >= (_Connection_flag->_Number - MyID)) ) { 
            LOG_INFO("sleeped");
            boost::this_thread::sleep(boost::posix_time::milliseconds(20));
            continue;
        }
        line = _Connection_buffer[index];
        if(line.size()<_storage_Count_Connection)
            continue;
        part = line.substr(_column_ConnectionConditionLocation, ConnectionCondition.length()   5);
        if (part.find("My Packet") == std::string::npos) {      //assume always false.
            LOG_INFO("Part: %s, Condition: %s", part.c_str(), ConnectionCondition.c_str());
            continue;
        }                                    
        boost::split(_CStorage,line,boost::is_any_of(" "));
        t = _CStorage[_column_ConnectionUserIP];   
        auto endSource = t.find("/", 0);
        srcIP_str = t.substr(0, endSource);
        try {
            srcIP_num = boost::asio::ip::address_v4::from_string(srcIP_str).to_ulong();
        } catch (...) {
            continue;
        }
        entryItem = searchIPTable(srcIP_num);
        if (entryItem == NULL) {
            continue;
        }
        int ok = processConnection(srcIP_num, connectionPayload1, connectionPayload2, amp;_CStorage);
        if (!ok) {
            continue;
        }
        auto startSource = t.find("/", 8)   1;
        endSource = t.find("-", startSource);            
        connectionPayload2 =t.substr(startSource, endSource - startSource);

        connectionPayload2 =_CStorage[_column_ConnectionProtocol];

        entryItem->_mtx.lock();
        if (entryItem->InUse != false) {
            connectionPayload = entryItem->payload1;
            connectionPayload  = connectionPayload1;
            connectionPayload  = entryItem->payload2;
            connectionPayload  = connectionPayload2;
        }
        entryItem->_mtx.unlock();
    }
    gettimeofday(amp;end, NULL);
    secs  = end.tv_sec  - start.tv_sec;
    usecs = end.tv_usec - start.tv_usec;
    mtime = ((secs) * 1000   usecs/1000.0)   0.5;
    LOG_INFO("Worker %d :Elapsed time for %lu times running Connection Worker is %ld millisecsn",MyID,index, mtime);  

    LOG_INFO("Connection Worker %d :stopped",MyID);
}
  

итак, теперь есть проблема, которая сводит меня с ума. обработка всех пакетов с использованием одного, двух или n потоков занимает одинаковое время.
как было сказано ранее, при многопоточности я уверен, что каждый поток обрабатывает только пакеты _Max_Element_Connection_buffer / _ConnectionThreadCount.

Я запустил свою программу на виртуальной Ubuntu 14.04, которая имеет 20 ГБ оперативной памяти и 4 процессора. основная операционная система Windows 8 и имеет 8 процессоров. спецификация одного из моих обычных процессоров Ubuntu показана ниже:

процессор: 3

vendor_id: GenuineIntel

семейство процессоров: 6

модель: 60

название модели: процессор Intel (R) Core (TM) i5-4460 с частотой 3,20 ГГц

пошаговое выполнение: 3

частота процессора: 3192,718

размер кэша: 6144 КБ

физический идентификатор: 0

братьев и сестер: 4

идентификатор ядра: 3

количество ядер процессора: 4

результаты обработки моей программы с помощью 1, 2, 4 и 8 потоков следующие:

Количество элементов _Connection_buffer = 10000

использование одного потока:

 Worker 0 :Elapsed time for 10000 times running Connection Worker is 149 millisecs
  

использование 2 потоков:

 Worker 0 :Elapsed time for 10000 times running Connection Worker is 122 millisecs
Worker 1 :Elapsed time for 10001 times running Connection Worker is 127 millisecs

using 4 threads:
Worker 0 :Elapsed time for 10000 times running Connection Worker is 127 millisecs
Worker 1 :Elapsed time for 10002 times running Connection Worker is 129 millisecs
Worker 2 :Elapsed time for 10001 times running Connection Worker is 138 millisecs
Worker 3 :Elapsed time for 10003 times running Connection Worker is 140 millisecs
  

использование 8 потоков.

 Worker 0 :Elapsed time for 10007 times running Connection Worker is 135 millisecs
Worker 1 :Elapsed time for 10000 times running Connection Worker is 154 millisecs
Worker 2 :Elapsed time for 10002 times running Connection Worker is 153 millisecs
Worker 3 :Elapsed time for 10003 times running Connection Worker is 158 millisecs
Worker 4 :Elapsed time for 10006 times running Connection Worker is 169 millisecs
Worker 5 :Elapsed time for 10004 times running Connection Worker is 170 millisecs
Worker 6 :Elapsed time for 10005 times running Connection Worker is 176 millisecs
Worker 7 :Elapsed time for 10001 times running Connection Worker is 178 millisecs
  

Комментарии:

1. При беглом взгляде как на ваш код, так и на выходные данные, кажется, что сам поток выполняет примерно одинаковый объем работы. Это означает, что 4 потока будут выполнять в 4 раза больше работы, чем один поток …. и каждый поток будет занимать одинаковое количество времени. Это означает, что ваша проблема заключается в логике измерения.