[英]Low UDP throughput comparing to iperf UDP performance
通过iperf2工具测量Windows PC和基于Zynq的设备之间的UDP吞吐量时,通过专用的1Gb以太网链路,我的速度约为950 Mb / s。 但是,当在PC上使用我自己的UDP应用程序时,我得到的速度仅为50 Mb / s左右,这比iperf测得的吞吐量大大降低。 当然,在我的UDP应用程序中,我没有任何处理,只有while循环(我在其中调用sendto函数)使用1470字节大小的UDP数据包。 XAPP1026提供了Zynq设备上的应用程序,因此不是我的。 我正在查看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;
}
因此,我的主要问题是如何像iperf一样最大化UDP吞吐量?
更新:我切换到Ubuntu PC。 结果有所不同,但仍然有一些随机事件在发生。 我要做的第一件事是为eth0设置IP地址( ifconfig eth0 172.16.0.200 netmask 255.255.255.0
)和网关地址( route add default gw 172.16.0.1
)。 当我使用iperf -c 172.16.0.215 -i 5 -t 25 -u -b 1000m
运行iperf时,我的速度约为800 Mbits / sec。 但是,以相同的方式运行了几次iperf之后,突然间我开始只获得大约15 Mbits / sec甚至更低的速度。 我发现需要再次设置IP,网络掩码和网关地址才能获得800 Mbits / sec。 另外,我的UDP应用程序的行为也相同。 在运行用于设置IP地址的命令后,我正在测量957 Mbits / sec( MAXUDP
设置为1470)。 但是经过几次迭代后,它的速度降低到了11 Mbit / s左右。 然后,我再次设置IP地址,该行为重复出现。 因此,正如Kariem在回答中所说的那样,问题不在于代码本身,而在于某些OS,netif配置相关的东西。 但是,我必须在Windows上运行UDP应用程序,因此我需要弄清楚那里发生了什么。 如果你们对Windows中可能发生的事情有任何想法,请现在让我。
计算吞吐量的方式有误。 您的大小以字节为单位设置,因此,在iperf以位为单位的同时,您以字节为单位计算吞吐量。
更改
printf("Throughput: %d.%3d MB/s\n", (tr_size/neval)/end/1000, (tr_size/neval)/end - (tr_size/neval)/end/1000);
对此
printf("Throughput: %d.%3d MB/s\n", ((tr_size/neval)/end/1000)*8, (tr_size/neval)/end - ((tr_size/neval)/end/1000)*8);
我在计算机上运行了一个版本的代码,吞吐量达到1GB。 这里是
#include <netinet/in.h>
#include <string.h>
#include <sys/time.h>
#include <cstdio>
#include <arpa/inet.h>
#include <fcntl.h>
#define MAXUDP 1470
#define SERV_PORT 5001
static inline long int getCurTimeInMs()
{
struct timeval tp;
gettimeofday(&tp, NULL);
return tp.tv_sec * 1000 + tp.tv_usec / 1000;
}
int main(int argc, char** argv)
{
int sockfd;
struct sockaddr_in servaddr;
char sendline[MAXUDP];
int i;
int j;
const int tr_size = ( 10000 * 1024*1024 );
const int npackets = ( tr_size / MAXUDP );
const int neval = 2;
int optval;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = inet_addr("10.0.1.2");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
connect(sockfd, (const sockaddr*) &servaddr, sizeof(servaddr));
optval = 208*1024;
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char*) &optval, sizeof optval);
long int start = 0, end = 0;
for ( i = 1; i <= neval; i++ )
{
start = getCurTimeInMs();
for ( j = 0; j < npackets/neval; j++ )
sendto(sockfd, sendline, MAXUDP, 0, NULL, NULL);
end = getCurTimeInMs() - start;
printf("Time elapsed: %d sec.\n", end/1000);
printf("Throughput: %d.%3d MB/s\n", (tr_size/neval)/end/1000 * 8, (tr_size/neval)/end - (tr_size/neval)/end/1000);
}
return 0;
}
为什么定义MAXUDP 1470? 尝试将其设置为65535,再次测量并在此处报告。
您不应将以太网帧大小(1500字节)与UDP数据报大小混淆。 不同的东西。 让IP堆栈代替您的应用程序进行必要的分段。 那可能会更有效率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.