Измерение скорости генерации пакетов в C под Linux
Я пишу сетевую программу как часть сетевого проекта. Программа генерирует пакет пакетов (TCP используется для связи с использованием API сокетов Беркли) и отправляет его на определенный порт и измеряет полученные ответы. Программа работает отлично, но я хотел сделать небольшие подсчеты, например, сколько данных на самом деле генерирует моя программа. То, что я пытался сделать, - это то, что я измерил время до и после процедуры кода, которая отправляет пакеты, и разделил все данные на это время, то есть: в общей сложности 799 пакетов отправляется за один раз процедуры, где каждый пакет размером 82 байта так:
799 х 82 х 8 = 524144 бит. Измеренное время было = 0,0001 с. Скорость передачи данных 524144 / 0,0001 = 5,24 Гбит / с.
Вот кусок кода, который я попробовал:
struct timeval start,end;
double diffTime (struct timeval* start, struct timeval* end)
{
double start_sec = ((double) start->tv_sec) + (double) start->tv_usec / 1000000.00;
double end_sec = ((double) end->tv_sec) + (double) end->tv_usec / 1000000.00;
return (end_sec - start_sec);
}
while(1){
gettimeofday(&start, NULL); // getting start time
*/ Call packet sending routine */
gettimeofday(&end, NULL);
printf("Time taken for sending out a batch is %f secs\n", diffTime(&start,&end));
}
Я хотел подтвердить, правильно ли я подхожу к проблеме или нет. Кроме того, если это правильный метод, есть ли способ узнать, с какой скоростью фактически пакеты выходят из сети, то есть с фактической физической скоростью пакетов из интерфейса Ethernet? Можем ли мы оценить, какова будет разница между скоростью пакетов, которую я вычислил в программе (которая находится в режиме пользователя, и я ожидаю, что она будет намного медленнее, когда барьер пользователь / ядро преодолевается при системных вызовах) и фактической скоростью пакетов? Вся помощь очень ценится.
Благодарю.
1 ответ
Я подозреваю, что это не то, что вы хотите. То, что у вас есть, даст вам информацию, но, возможно, не о том, как ее улучшить.
Как правило, я беспокоюсь о том, чтобы измерить задержку при подключении к сокету send/recv. Обычно это связано с измерением того, сколько времени я провожу между send () или как долго я жду в какой-либо форме recv().
Есть пара вещей, за которыми обычно следят. Вы полагаетесь на сетевой уровень, чтобы собирать и буферизовать ваши посылки, или вы буферизуете и делаете отправку только тогда, когда хотите, чтобы данные вышли? Если в последнем случае вы обычно хотите отключить буферизацию nagle (см. Setsockopt и TCP_NODELAY) - но будьте осторожны, код не регрессирует.
Далее идет буферизация. Вы, вероятно, измеряете время, за которое данные попадают в буферизацию сокета, что будет практически мгновенным. Если вы используете потоковую передачу с подтверждением / согласованием ответных пакетов, это будет в среднем нормально в течение длительного периода. Вы можете связываться с буферизацией с помощью setsockopt() и SO_RCVBUF/SO_SNDBUF.
Я собираюсь достичь немного дальше. Если вы измеряете код, а не физическую сеть для perf, и отправляете и получаете пакеты в максимально больших блоках, есть еще две вещи, которые я бы обычно проверял.
У вас есть протокол типа ACK. Код отправляет / recv в шаблон в принципе. Если так, то задержка, вероятно, будет самой большой проблемой. Существует множество способов решения этой проблемы: от разрешения нескольких ожидающих запросов, которые передаются независимо друг от друга, до реализации скользящих окон. Основная идея заключается в том, чтобы просто не прерывать поток данных.
Наконец, если вы имеете дело с recv (), вы обычно не хотите блокировать в recv, если вы действительно не хотите обрабатывать только одно отношение сокетов на поток / процесс. Решение старой школы было выбрано select(), и оно все еще жизнеспособно для разумной масштабируемости. Для более масштабных решений вы можете обратиться к epoll(linux), kevents(osx) или IOCP(windows). Это позволяет вам перемещать бухгалтерию и (иногда) пул потоков обратно в ОС. Это то место, где вы хотите быть, если ваша проблема действительно в том, сколько данных я могу выкачать с этого NIC; но редко требуется, если вы не обрабатываете несколько соединений.
Извините, если я пропустил то, что вы действительно спрашивали, но я попытался осветить общие проблемы.