关于高速低延迟收发UDP网络数据包的效率优化
最近观摩UHD驱动关于UDP收发包的代码,发现一些优化方法,特记录下来。
在使用UHD这种超大规模数据收发的网络设备,是必须要求调大主机网卡MTU值来提升收发包效率,才能达到理想的传输速度。
目前大多数据网卡驱动设置中有巨帧(Jumbo Frame)设置,用于加大MTU值的分包值上限。
在查看UHD驱动关于MTU值和UDP收发代码时,发现收发代码使用了Windows上的重叠端口(OVERLAPPED I/O)。
重叠端口是Windows上一套WSA开头的套接字相关操作API,增加了套接字事件WSAEVENT,可以在一次WSASend()或者WSARecv()时,使用用户设置的多个内存缓冲区异步操作数据收发,操作结果通过套接字事件通知。因为是直接使用的用户申请的内存缓冲区提交操作,不用将数据在驱动层和用户层之间再拷贝一次,因此能一定程度上提高收发效率。
在重叠端口代码中,看到下面这一段:
/***********************************************************************
* Check registry for correct fast-path setting (windows only)
**********************************************************************/
#ifdef HAVE_ATLBASE_H
# define CHECK_REG_SEND_THRESH
# include <atlbase.h> //CRegKey
static void check_registry_for_fast_send_threshold(const size_t mtu)
{
static bool warned = false;
if (warned)
return; // only allow one printed warning per process
CRegKey reg_key;
DWORD threshold = 1024; // system default when threshold is not specified
if (reg_key.Open(HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Services\\AFD\\Parameters",
KEY_READ)
!= ERROR_SUCCESS
or reg_key.QueryDWORDValue("FastSendDatagramThreshold", threshold)
!= ERROR_SUCCESS
or threshold < mtu) {
UHD_LOGGER_WARNING("UDP")
<< boost::format(
"The MTU (%d) is larger than the FastSendDatagramThreshold (%d)!\n"
"This will negatively affect the transmit performance.\n"
"See the transport application notes for more detail.\n")
% mtu % threshold;
warned = true;
}
reg_key.Close();
}
#endif /*HAVE_ATLBASE_H*/
代码和提示信息,大意就是就是如果MTU值大于注册表这个FastSendDatagramThreshold的值,就打印提示会影响发送效率的提示信息。
而Windows系统这个FastSendDatagramThreshold阈值默认是
DWORD threshold = 1024; // system default when threshold is not specified
通常网卡的默认MTU值是1500,实际UDP可用包大小是1500-28=1472bytes,很显然大于1024。
因此,在使用了网卡巨帧的情况下,此处要根据应用应用程序分包情况修改注册表这个FastSendDatagramThreshold的阈值。