При измерении пропускной способности UDP между ПК с Windows и устройством на базе Zynq с помощью инструмента iperf2 я получаю около 950 Мбит / с по выделенному каналу Ethernet 1 Гбит. Однако при использовании моего собственного приложения UDP на ПК я получаю только около 50 Мбит / с, что значительно ниже пропускной способности, измеренной iperf. Конечно, в моем приложении UDP у меня нет никакой обработки, только цикл while, в котором я вызываю функцию sendto, с пакетами UDP размером 1470 байт. Приложение на устройстве Zynq предоставлено XAPP1026, поэтому оно не мое. Я смотрю на код iperf, пытаясь понять, что они делают по-другому, но в основном я не могу найти какие-либо параметры сокета или udp или что-то подобное, что они делают, чтобы максимизировать пропускную способность UDP.
Вот код основной функции (определение MAXUDP равно 1470):
int main(int argc, char** argv)
{
int sockfd;
struct sockaddr_in servaddr;
char sendline[MAXUDP];
int i;
int j;
const int tr_size = ( 200 * MB );
const int npackets = ( tr_size / MAXUDP );
const int neval = 2;
DWORD start;
DWORD end;
int optval;
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 1), &wsaData) != 0 )
{
printf( "Err: %d\n", WSAGetLastError() );
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = inet_addr("172.16.0.215");
sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
Connect(sockfd, (const SA*) &servaddr, sizeof(servaddr));
optval = 208*KB;
Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char*) &optval, sizeof optval);
prep_data(sendline, MAXUDP);
for ( i = 1; i <= neval; i++ )
{
start = GetTickCount();
for ( j = 0; j < npackets/neval; j++ )
sendto(sockfd, sendline, MAXUDP, 0, NULL, NULL);
end = GetTickCount() - start;
printf("Time elapsed: %d sec.\n", end/1000);
printf("Throughput: %d.%3d MB/s\n", (tr_size/neval)/end/1000, (tr_size/neval)/end - (tr_size/neval)/end/1000);
}
return 0;
}
Итак, мой главный вопрос заключается в том, как максимизировать пропускную способность UDP так же, как это делает iperf?
ОБНОВЛЕНИЕ: я перешел на ПК с Ubuntu. Результаты разные, но все же происходят некоторые случайные вещи. Первое, что я делаю, это устанавливаю IP-адреса для eth0 (ifconfig eth0 172.16.0.200 netmask 255.255.255.0
) и адрес шлюза (route add default gw 172.16.0.1
). Когда я запускаю iperf с iperf -c 172.16.0.215 -i 5 -t 25 -u -b 1000m
), я получаю около 800 Мбит/сек. Однако, после нескольких запусков iperf таким же образом, внезапно я начинаю получать только около 15 Мбит / с или даже намного меньше. Я понял, что мне нужно снова установить IP, сетевую маску и адреса шлюза, чтобы получить 800 Мбит/сек. Кроме того, мое приложение UDP ведет себя точно так же. Я измеряю 957 Мбит/с (с MAXUDP
, установленным на 1470) после того, как я выполнил команды для установки IP-адресов. Но после нескольких итераций он замедляется примерно до 11 Мбит/с. Затем я снова устанавливаю IP-адреса, и поведение повторяется. Итак, как сказал Карием в своем ответе, проблема не в самом коде, а в некоторых ОС, связанных с конфигурацией netif. Однако я должен запустить свое UDP-приложение в Windows, поэтому мне нужно выяснить, что там происходит. Если у вас есть какие-либо идеи о том, что может происходить в Windows, пожалуйста, дайте мне сейчас.
sendto()
! Вот как вы можете выяснить, сколько байтов было фактически отправлено, а не отброшено.send()
не всегда отправляет все байты, которые вы просили отправить, поэтому вы, вероятно, неправильно измеряете, когда устанавливаете большие размеры буфера. - person John Zwinck   schedule 27.04.2017sendto()
(никогда не возвращает значение меньше MAXUDP). В общем, результаты одинаковые. - person Irie   schedule 27.04.2017MAXUDP
уменьшают общее количество вызововsendto()
. Еслиsendto()
всегда сообщает об успешной отправкеMAXUDP
байтов для каждого проверенного до сих пор значенияMAXUDP
, то стоит увеличитьMAXUDP
еще больше, чтобы уменьшить количество вызовов, потому что системные вызовы сравнительно дороги. Абсолютный максимальный размер полезной нагрузки, поддерживаемый протоколом UDP, составляет 65 507 байт. - person John Bollinger   schedule 27.04.2017MAXUDP
на 65507 и получаю скорость до 695 Мбит/с. С другой стороны, я заметил, что iperf также вызываетsendto()
с номером 1470 и получает еще более высокие результаты. - person Irie   schedule 27.04.2017