Я пишу код, который получает необработанные пакеты ethernet (без TCP/UDP) каждые 1 мс с сервера. Для каждого полученного пакета мое приложение должно ответить 14 необработанными пакетами. Если сервер не получает 14 пакетов до того, как он отправит пакет, запланированный на каждые 1 мс, тогда сервер вызывает тревогу, и приложение должно выйти из строя. Связь между сервером и клиентом - это одна к одной ссылке.
Сервер - это аппаратное обеспечение (FPGA), которое генерирует пакеты с точным интервалом 1 мс. Клиентское приложение работает на Linux (RHEL/Centos 7) с 10G SolarFlare NIC.
Моя первая версия кода похожа на эту
while(1)
{
while(1)
{
numbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
if(numbytes > 0)
{
//Some more lines here, to read packet number
break;
}
}
for (i=0;i<14;i++)
{
if (sendto(sockfd,(void *)(sym) , sizeof(sym), 0, NULL, NULL) < 0)
perror("Send failed\n");
}
}
Я измеряю время приема, беря отметки времени (используя clock_gettime
) перед вызовом recvfrom
и один за ним, я печатаю разницу во времени этих временных меток и печатаю их каждый раз, когда разница во времени превышает допустимый диапазон 900-1100 нас.
Проблема, с которой я сталкиваюсь, заключается в том, что время приема пакета колеблется. Что-то вроде этого (отпечатки находятся в микросекундах)
Decode Time : 1234
Decode Time : 762
Decode Time : 1593
Decode Time : 406
Decode Time : 1703
Decode Time : 257
Decode Time : 1493
Decode Time : 514
and so on..
И иногда время декодирования превышает 2000us, и приложение будет ломаться.
В этой ситуации приложение будет прерываться от 2 секунд до нескольких минут.
Параметры, которые я использовал до сих пор.
- Настройка близости к изолированному ядру.
- Настройка приоритетов планирования с максимальным значением с помощью
SCHED_FIFO
- Увеличение размеров буфера сокетов
- Настройка сетевого интерфейса прерывает сродство к тому же ядру, которое обрабатывает приложение
- Скручивание
recvfrom
с помощью вызововpoll(),select()
.
Все эти параметры дают значительное улучшение по сравнению с исходной версией кода. Теперь приложение будет работать в течение ~ 1-2 часов. Но этого все еще недостаточно.
Несколько наблюдений:
- Я получаю огромный дамп этих отпечатков времени декодирования, когда я принимаю ssh-сессии на Linux-машине во время работы приложения (что заставляет меня думать, что сетевая связь через другой интерфейс Ethernet 1G создает помехи для интерфейса Ethernet 10G).
- Приложение работает лучше в RHEL (время работы около 2-3 часов), чем Centos (время работы около 30 минут - 1,5 часа)
- Время выполнения также зависит от машин Linux с различными конфигурациями оборудования с той же ОС.
Просьба указать, есть ли какие-либо другие способы улучшения времени выполнения приложения.
Спасибо заранее.