Сетевые сокеты C ++, SCTP и размер пакета

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

Есть два вопроса об эффективности протокола прикладного уровня, который я реализовал:

1) Размер пакета

В настоящее время я использую максимальный размер пакета 64 байта. Вы можете найти много постов, в которых обсуждаются слишком большие размеры пакетов, но могут ли они быть слишком маленькими? Так как SCTP позволяет мне читать по одному пакету за раз — по аналогии с UPD — при этом гарантируя доставку по порядку — по аналогии с TCP — это значительно упростило реализацию. Однако, если я правильно понимаю, это будет стоить один системный вызов за каждый раз, когда я отправляю пакет. Влияет ли количество системных вызовов на производительность? Смогу ли я сэкономить много циклов ЦП, посылая сообщения в пакетах большими пакетами, то есть 1024 — 8192 байта?

2) Чтение и запись буферов

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

Опция 1

void Network::ReceivePacket(char* packet)
{
uint8_t param1;
uint16_t param2
uint32_t param3;

memcpy(&param1, packet, 1);
memcpy(&param2, packet+1, 2);
memcpy(&param3, packet+3, 4);

// Handle the packet here
}

void Network::SendPacket(uint8_t param1, uint16_t param2, uint32_t param3)
{
char packet[7]

memcpy(&packet, &param1, 1);
memcpy(&packet+1, &param2, 2);
memcpy(&packet+3, &param3, 4);

// Send the packet here
}

Вариант 2

void Network::ReceivePacket(char* packet)
{
uint8_t param1;
uint16_t param2
uint32_t param3;

param1 = *((uint8_t*)packet);
param2 = *((uint16_t*)packet+1);
param3 = *((uint32_t*)packet+3);

// Handle the packet here
}

void Network::SendPacket(uint8_t param1, uint16_t param2, uint32_t param3)
{
char packet[7]

*((uint8_t*)packet) = param1;
*((uint16_t*)packet+1) = param2;
*((uint32_t*)packet+3) = param3;

// Send the packet here
}

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

Любые отзывы, конечно, приветствуются.

2

Решение

Насколько я знаю, компиляторы оптимизируют вызовы memcpy, в частности, поэтому вам, вероятно, следует использовать его.

О вашем первом вопросе:

  • Резюме: Сделайте размер вашего пакета как можно большим и избегайте возможного увеличения производительности процессора.

syscallсистемный вызов — это ваша ОС, отвечающая или обрабатывающая ваш запрос, и каждый раз, когда ваш запрос выполняется в ядре, это умеренный объем работы.
Если честно, я не знаком с SCTP По сути, я не занимался программированием сокетов с тех пор, как в последний раз работал над некоторыми вещами и создал сервер через TCP. Я помню, MTU для соответствующего элемента физического уровня был 1500Я также вспоминаю реализацию моего размера пакета как 1450-1460так как я пытался получить максимальный размер пакета под 1500 крышка.

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

0

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

Если вы хотите свести к минимуму количество системных вызовов и отправляете и получаете несколько сообщений одновременно, возможно, вы захотите использовать (только для Linux) sendmmsg() а также recvmmsg().

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

0

Я бы не стал превышать 1024 для размера буфера лично. У меня возникли некоторые проблемы во время выполнения при использовании пакетов более 1500, но 1024 — это, конечно, от 4 до 5 степени, что делает его замечательным в использовании.
Это возможно, но я бы не советовал. Я бы сделал отдельный поток для получения пакетов, используя recvmsg (), чтобы вы могли использовать несколько потоков. Я нашел, что это работает чудесно.
Основной смысл SCTP — это несколько потоков, поэтому я бы в полной мере воспользовался этим. Вы просто должны убедиться, что данные возвращаются в правильном порядке после того, как все получено (что требует определенной работы).

0
По вопросам рекламы [email protected]