Как уменьшить использование процессора при передаче данных по портам TCP в реальном времени

У меня есть программа сокетов, которая действует как клиент и сервер.

Он инициирует соединение на входном порте и считывает данные с него. В реальном времени он считывает данные с входного порта и отправляет данные (запись за записью) на выходной порт.

Проблема здесь в том, что при отправке данных на выходной порт загрузка ЦП увеличивается до 50%, а это недопустимо.

while(1)
{
if(IsInputDataAvail==1)//check if data is available on input port
{
//condition to avoid duplications while sending
if( LastRecordSent < LastRecordRecvd )
{
record_time temprt;
list<record_time> BufferList;
list<record_time>::iterator j;
list<record_time>::iterator i;

// Storing into a temp list
for(i=L.begin(); i != L.end(); ++i)
{
if((i->recordId > LastRecordSent) && (i->recordId <= LastRecordRecvd))
{
temprt.listrec = i->listrec;
temprt.recordId = i->recordId;
temprt.timestamp = i->timestamp;
BufferList.push_back(temprt);
}
}

//Sending to output port
for(j=BufferList.begin(); j != BufferList.end(); ++j)
{
LastRecordSent = j->recordId;

std::string newlistrecord = j->listrec;
newlistrecord.append("\n");
char* newrecord= new char [newlistrecord.size()+1];
strcpy (newrecord, newlistrecord.c_str());

if ( s.OutputClientAvail() == 1) //check  if output client is available
{
int ret = s.SendBytes(newrecord,strlen(newrecord));
if ( ret < 0)
{
log1.AddLogFormatFatal("Nice Send Thread : Nice Client Disconnected");
--connected;
return;
}
}
else
{
log1.AddLogFormatFatal("Nice Send Thread : Nice Client Timedout..connection closed");
--connected; //if output client not available disconnect after a timeout
return;
}
}

}
}

//  Sleep(100); if we include sleep here CPU usage is less..but to send data real time I need to remove this sleep.
If I remove Sleep()...CPU usage goes very high while sending data to out put port.
}//End of while loop

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

-1

Решение

В указанном коде есть два потенциальных приемника ЦП. Во-первых, внешний цикл:

while (1)
{
if (IsInputDataAvail == 1)
{
// Not run most of the time
}

// Sleep(100);
}

Учитывая, что вызов Sleep значительно снижает загрузку вашего процессора, этот спин-цикл является наиболее вероятным виновником. Это выглядит как IsInputDataAvail переменная, установленная другим потоком (хотя это может быть макрос препроцессора), что будет означать, что почти весь этот процессор используется для выполнения этой одной инструкции сравнения и пары переходов.

Способ вернуть потерянную мощность — заблокировать, пока не станет доступен ввод. Ваш поток чтения, вероятно, уже делает это, поэтому вам просто нужен какой-то семафор для связи между ними, с системным вызовом, чтобы заблокировать поток вывода. Там, где это возможно, идеальным вариантом будет sem_wait() в выходной поток, прямо в верхней части вашего цикла, и sem_post() в потоке ввода, где он в настоящее время устанавливает IsInputDataAvail, Если это не возможно, трюк с самотрубкой может сработать.

Второй потенциальный приемник процессора находится в s.SendBytes(), Если положительный результат указывает, что запись была полностью отправлена, то этот метод должен использовать цикл. Вероятно, он использует блокирующий вызов для записи записи; если это не так, то это может быть переписано для этого.

Кроме того, вы можете переписать половину приложения для использования select(), poll()или аналогичный метод для объединения чтения и записи в одном потоке, но это слишком много работы, если ваша программа в основном уже завершена.

0

Другие решения

  if(IsInputDataAvail==1)//check if data is available on input port

Избавься от этого. Просто читать из входного порта. Он будет блокироваться, пока данные не будут доступны. Именно на это уходит большая часть вашего процессорного времени. Однако есть и другие проблемы:

          std::string newlistrecord = j->listrec;

Здесь вы копируете данные.

          newlistrecord.append("\n");

char* newrecord= new char [newlistrecord.size()+1];
strcpy (newrecord, newlistrecord.c_str());

Здесь вы снова копируете те же данные. Вы также динамически распределяете память, и вы также утечка.

         if ( s.OutputClientAvail() == 1) //check  if output client is available

Я не знаю, что это делает, но вы должны удалить это. Следующая отправка — время проверки на наличие ошибок. Не пытайтесь угадать будущее.

          int ret = s.SendBytes(newrecord,strlen(newrecord));

Здесь вы пересчитываете длину строки, которую вы, вероятно, уже знали во время установки j->listrec, Было бы гораздо эффективнее просто позвонить s.sendBytes() непосредственно с j->listrec а затем снова с "\n" чем делать все это. TCP все равно объединит данные.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector